asciidoctor / asciidoctor-pdf

:page_with_curl: Asciidoctor PDF: A native PDF converter for AsciiDoc based on Asciidoctor and Prawn, written entirely in Ruby.
https://docs.asciidoctor.org/pdf-converter/latest/
MIT License
1.14k stars 500 forks source link

document how to show author etc. without title page #2439

Closed das-g closed 10 months ago

das-g commented 1 year ago

Add a use case example that makes author, revdate and revremark visible in document types (e.g. articles) without a title page, by hooking into the converter function for the document title and adding these infos in a line below it.

Workaround for #1883

See https://github.com/asciidoctor/asciidoctor-pdf/issues/1883#issuecomment-1637196810

das-g commented 1 year ago

Is this something to be listed in the changelog?

das-g commented 1 year ago

How can I render the asciidoctor-pdf documentation to test this change?

mojavelinux commented 10 months ago

In order to test the documentation, you update the [Antora playbook] for docs.asciidoctor.org to point to your local repository instead of the remote one, then specify the branch name in the branches key. For example:

  - url: /path/to/asciidoctor-pdf
    branches: show-author-and-date-and-revremark-in-articles-converter-example
    # or use the value HEAD if the branch is currently checked out in git
    start_path: docs

Then run Antora:

npx antora antora-playbook.yml

Alternately, you can create a separate playbook file that only has a single content source that points to your location repository.

mojavelinux commented 10 months ago

Please use || and && in place of or and and respectively. The former are the preferred style in the Ruby language.

mojavelinux commented 10 months ago

Also, please use single quotes for strings that do not have interpolation (e.g., variable references). For strings that do, use the enclosure %() instead of double quotes. The latter is specifically an Asciidoctor style, but one that has worked for us.

mojavelinux commented 10 months ago

Here's a more complete implementation:

class PDFConverterArticleTitleWithAuthorAndDate < (Asciidoctor::Converter.for 'pdf')
  register_for 'pdf'

  def ink_general_heading doc, title, opts
    return super unless opts[:role] == :doctitle
    if (top_margin = @theme.heading_h1_margin_page_top || @theme.heading_margin_page_top) > 0
      move_down top_margin
    end
    pad_box @theme.heading_h1_padding do
      if (transform = resolve_text_transform opts)
        title = transform_text title, transform
      end
      if (inherited = apply_text_decoration font_styles, :heading, 1).empty?
        inline_format_opts = true
      else
        inline_format_opts = [{ inherited: inherited }]
      end
      typeset_text_opts = { color: @font_color, inline_format: inline_format_opts }.merge opts
      typeset_text title, (calc_line_metrics (opts.delete :line_height) || @base_line_height), typeset_text_opts 
    end
    if (revremark = doc.attr 'revremark') || doc.author || doc.revdate
      move_down @theme.heading_h1_details_margin_top || 0
      theme_font_cascade [:base, :heading_h1_details] do
        revdate_sep = doc.author && doc.revdate ? ' &#x2013; ' : ''
        revremark_sep = ((doc.author || doc.revdate) && revremark) ? ' | ' : ''
        ink_prose %(#{doc.author || ''}#{revdate_sep}#{doc.revdate || ''}#{revremark_sep}#{revremark || ''}), align: opts[:align]
      end
    end
    margin_bottom @theme[:heading_h1_margin_bottom] || @theme.heading_margin_bottom
  end
end

I have reuse the built-in heading_h1 category since that is the category that targets the doctitle in an article (the only time this method would be called for an h1 heading). I introduced a details subcategory to control the formatting of the details line rather than just defaulting to the base font settings.

Obviously, this could be taken much further, but I think it is a good start.

mojavelinux commented 10 months ago

Would you be willing to integrate these updates? If not, I'm happy to continue this. I just don't want to step over you if you want to see it through.

das-g commented 10 months ago

Would you be willing to integrate these updates?

In general, yes, but I'll first have to read and understand them, and won't get around to that before the weekend.

mojavelinux commented 10 months ago

That's great! I'll give you space to work then. And please don't feel rushed. As you can see from this thread, it even took me months to follow up.

das-g commented 10 months ago

How can I render the asciidoctor-pdf documentation to test this change?

In order to test the documentation, you update the [Antora playbook] for docs.asciidoctor.org to point to your local repository instead of the remote one, then specify the branch name in the branches key. For example:

  - url: /path/to/asciidoctor-pdf
    branches: show-author-and-date-and-revremark-in-articles-converter-example
    # or use the value HEAD if the branch is currently checked out in git
    start_path: docs

Then run Antora:

npx antora antora-playbook.yml

Alternately, you can create a separate playbook file that only has a single content source that points to your location repository.

Huh. You might want to offer a single-command way to do that, that doesn't require the user to clone additional repositories or to modify or create additional files, or you risk casual contributors (like me :speak_no_evil:) to take on a The "the most interesting man in the world" meme, captioned "I don't always test my contribution", "but when I do, I do it after getting it merged" approach. :see_no_evil:

mojavelinux commented 10 months ago

This is the strategy we decided to take. I'm happy to add information to the README about how to configure and run the docs on a branch (similar to how we document how to test changes), but we're not going to change the docs set up because someone is unwilling to follow those instructions. If you want to contribute, this is what it takes. I do it and so does everyone else who helps to maintain the docs. If someone doesn't like it, then they are not the right candidate to contribute to this project and there is nothing we can do about that. It is their decision.

mojavelinux commented 10 months ago

I have added documentation. As you can see, it is not necessary to clone the docs.asciidoctor.org repository, though you do need to be able to run Antora (either using npx directly or using the Antora container). See https://github.com/asciidoctor/asciidoctor-pdf/blob/main/CONTRIBUTING-CODE.adoc#documentation

das-g commented 10 months ago

I have added documentation. As you can see, it is not necessary to clone the docs.asciidoctor.org repository, though you do need to be able to run Antora (either using npx directly or using the Antora container). See https://github.com/asciidoctor/asciidoctor-pdf/blob/main/CONTRIBUTING-CODE.adoc#documentation

Thank you! That's not single-step-only but (with the new documentation) sufficiently straight forward. :+1:

I wonder whether it could be automated by a script, but that might be hard without having it write to directories that user doesn't expect anything to be written to and it might also be hard to get it sufficiently portable between operating systems.

mojavelinux commented 10 months ago

I have considered adding the playbook file for single project mode to the repository, but I'm not convinced I want to encourage that, at least not until Antora Atlas is stable (which supports partial site builds properly). Once it is, I'm willing to revisit my position.

For now, the right way to build all the documentation is through the build at docs.asciidoctor.org. For those contributing, the steps I provided for single project mode should be sufficient. Like I said, if the person is not willing to follow at least those steps, then it doesn't seem to me like it is the right person to be contributing to the docs.

das-g commented 10 months ago

In your more complete implementation, @mojavelinux, is purpose of the part

    if (top_margin = @theme.heading_h1_margin_page_top || @theme.heading_margin_page_top) > 0
      move_down top_margin
    end
    pad_box @theme.heading_h1_padding do
      if (transform = resolve_text_transform opts)
        title = transform_text title, transform
      end
      if (inherited = apply_text_decoration font_styles, :heading, 1).empty?
        inline_format_opts = true
      else
        inline_format_opts = [{ inherited: inherited }]
      end
      typeset_text_opts = { color: @font_color, inline_format: inline_format_opts }.merge opts
      typeset_text title, (calc_line_metrics (opts.delete :line_height) || @base_line_height), typeset_text_opts 
    end

to get the rendering of the document title itself closer to how it's being done by the default implementation (with all the settings it might take into account)? If so, does it make sense to imitate or even duplicate that logic here?

Explaining this code for users (that might be unfamiliar with both, Asciidoctor PDF's internal APIs and conventions and the programming language Ruby) in a way that highlights its purpose and enables them to hack on it and modify it to fit their own need seems somewhat challenging.

das-g commented 10 months ago

Explaining this code for users (that might be unfamiliar with both, Asciidoctor PDF's internal APIs and conventions and the programming language Ruby) in a way that highlights its purpose and enables them to hack on it and modify it to fit their own need seems somewhat challenging.

Regarding that, I think we might have the problem, that the section introduced by this PR tries to cater to several potentially very different audiences:

  1. users that want to modify the rendering of the document title itself, in a way that fits their own need, but without a need for portability (i.e., not necessarily applicable to other documents)
  2. users that simply want the author, date and/or revision remark to to be visible in a non-book PDF rendering or their document
  3. developers that want to create broadly applicable extensions

I believe group 1 (document title modifiers) would need two things:

Group 3 might need an example and some explanations that indicates best practices on what settings, conventions etc. their extension should respect.

Group 2 is tricky. It might contain people unfamiliar with Ruby (and without time to invest in learning it profoundly) that really wouldn't want to get into the Asciidoctor PDF internals. They'd want the document header to be rendered just like the default implementation would do it, respecting all their settings. But they'd also want an example on how to make author, date and/or revision remark visible, simple enough that they can (with their limited knowledge) understand it sufficiently to know what to adapt and what not to modify how the author, date and/or revision remark are shown, without risking to break the rendering of the document title.

Assuming group 2 wants the author, date and/or revision remark to be shown below the document title but above the gap between the document title section and the beginning of the document body (like our example here currently does), maybe a new extension point between the end of the rendering of the actual document title and that gap (thus between the following two code lines:) https://github.com/asciidoctor/asciidoctor-pdf/blob/92348ec3dcb1f7b8bed8c27bba877d657b96ac39/lib/asciidoctor/pdf/converter.rb#L3291-L3292 and a simple example on how to use that would cater to its need best?

mojavelinux commented 10 months ago

to get the rendering of the document title itself closer to how it's being done by the default implementation

precisely.

mojavelinux commented 10 months ago

Explaining this code for users (that might be unfamiliar with both, Asciidoctor PDF's internal APIs and conventions and the programming language Ruby) in a way that highlights its purpose and enables them to hack on it and modify it to fit their own need seems somewhat challenging.

I don't really think we need to burden ourselves with explaining it. For the purpose of the use case, it's more important that it is adding the details without breaking the other functionality of the doctitle. If they are really interested in how it works, they can dive into trying to understand it as self study (or by asking in the chat).

mojavelinux commented 10 months ago

users that simply want the author, date and/or revision remark to to be visible in a non-book PDF rendering or their document

This is the target audience and, in my view, sufficient for the purpose of this docs change. It should maintain the existing behavior / configurability while adding the details. Let's not overthink it.

mojavelinux commented 10 months ago

Group 3 might need an example and some explanations that indicates best practices on what settings, conventions etc. their extension should respect.

If people need more explanation, they can ask in the chat. That's what it's there for.

mojavelinux commented 10 months ago

It might contain people unfamiliar with Ruby

We are not and never have catered to this group on this page. This page is for people who know how to extend a converter (or are willing to try) and just want something that will work so they can either use it as is or build on it in time. Again, let's not overthink this.

mojavelinux commented 10 months ago

maybe a new extension point between the end of the rendering of the actual document title and that gap

I don't want to add anything new to Asciidoctor PDF right now. It's necessary to work with what Asciidoctor PDF provides.

das-g commented 10 months ago

Explaining this code for users (that might be unfamiliar with both, Asciidoctor PDF's internal APIs and conventions and the programming language Ruby) in a way that highlights its purpose and enables them to hack on it and modify it to fit their own need seems somewhat challenging.

I don't really think we need to burden ourselves with explaining it. For the purpose of the use case, it's more important that it is adding the details without breaking the other functionality of the doctitle. If they are really interested in how it works, they can dive into trying to understand it as self study (or by asking in the chat).

Would it then make sense to (within the example) at least factor it out into a separate method, so that the easily hackable (and thoroughly explained) parts are separate from the touch-this-if-you-know-what-your're-doing parts?

mojavelinux commented 10 months ago

Would it then make sense to (within the example) at least factor it out into a separate method, so that the easily hackable (and thoroughly explained) parts are separate from the touch-this-if-you-know-what-your're-doing parts?

I'd certainly be okay with the override using its own method calls, sure. I tend to use the prefix ink_ (so it doesn't conflict with other methods that are node handlers). Something like ink_document_details or whatever you think is best.

das-g commented 10 months ago

I'm not trying to overthink, merely to take a step back and figure out whether we're headed in the right direction. :slightly_smiling_face:

users that simply want the author, date and/or revision remark to to be visible in a non-book PDF rendering or their document

This is the target audience […]

OK. It's the one I originally had in mind with this PR.

It might contain people unfamiliar with Ruby

We are not and never have catered to this group on this page. This page is for people who know how to extend a converter (or are willing to try) and just want something that will work so they can either use it as is or build on it in time. Again, let's not overthink this.

Makes sense.


Not all users of Asciidoctor PDF that want a date and author to be shown are (or should be required to be) programmers. (Or am I mistaken about the target audience of Asciidoctor PDF itself?)

So while I agree with both your statements quote above, do they together imply that the target audience of this example isn't really the target audience of the documentation page this PR would currently place it on? :thinking:

(But nonetheless, I guess with dissecting the example into several methods, we have a workable approach. :+1: I'll try to work that out for now.)

das-g commented 10 months ago

Would it then make sense to (within the example) at least factor it out into a separate method, so that the easily hackable (and thoroughly explained) parts are separate from the touch-this-if-you-know-what-your're-doing parts?

I'd certainly be okay with the override using its own method calls, sure. I tend to use the prefix ink_ (so it doesn't conflict with other methods that are node handlers). Something like ink_document_details or whatever you think is best.

I was more thinking factoring out the rendering of the document title, but actually, maybe it makes sense to factor out both. I'll try that and see how the example code looks.

mojavelinux commented 10 months ago

I'm not trying to overthink, merely to take a step back and figure out whether we're headed in the right direction.

I certainly appreciate that. I didn't mean for it to sound judgemental, but rather as an invitation to ourselves not to step too far back ;)

mojavelinux commented 10 months ago

Not all users of Asciidoctor PDF that want a date and author to be shown are (or should be required to be) programmers. (Or am I mistaken about the target audience of Asciidoctor PDF itself?)

When it comes to customizing the converter, we can make the assumption there is a programmer (or at least someone doing that task of a programmer) involved. The non-programmer audience must use the software as it is provided, perhaps customizing the theme (though even that requires some programming acumen).

If we were to add this feature into Asciidoctor PDF proper, then it would be available to our whole audience.

mojavelinux commented 10 months ago

at least someone doing that task of a programmer

I consider anyone willing to edit source code to be a programmer. Whatever level they consider themselves to be is their own determination. I will help them regardless.

mojavelinux commented 10 months ago

Can you ensure that the content uses sentence-per-line formatting. That means only creating a newline in a paragraph or principal list item text after a full stop (., !, or ?)? There should be no other wrapping in the source text.

mojavelinux commented 10 months ago

Thanks for updating! I'll have a look this weekend.

mojavelinux commented 10 months ago

This is excellent. Great work! And thank you for sticking with it and seeing it through.