brailleapps / dotify.formatter.impl

Provides an implementation of the formatter interfaces in dotify.api
GNU Lesser General Public License v2.1
0 stars 6 forks source link

Continuation of previous volume in TOC #106

Open PaulRambags opened 5 years ago

PaulRambags commented 5 years ago

As Dedicon I want to be able to configure a special entry that should appear in the TOC when a volume break occurs in the middle of a section. For instance, suppose Dotify decides to apply a volume break in Chapter 1, the TOC of the second volume should contain "Continuation of Chapter 1" and contents of the second chapter should start with "Contination of Chapter 1".

Notes:

  1. The pipeline has level1 .. level6 and Dotify has only sequences and blocks.
  2. First the OBFL interface must be changed.

Changes in OBFL:

Semantics:

Remarks on the changes in OBFL:

bertfrees commented 4 years ago

Overall, I like this design because it is simpler than most of the other solutions we discussed. Other solutions tried to minimize the duplication, but I don't think that has been a goal of OBFL in the past, and it shouldn't be because the typical use case of OBFL is that it is generated from another document.

The only reservations I have are the following:

Firstly, I'm not sure yet about the names "toc-text" and "toc-text-resumed", but that's not the most important part and we still have some time to think about it.

Secondly, while letting the referenced blocks determine the "scope" of the toc-entrys is a logical thing to do, is simple and yet powerful, it is not a super good fit for CSS (which I am of course primarily interested in) and will moreover complicate my CSS-to-OBFL implementation a bit. The reason I say it's not a super good fit for CSS is because CSS basically considers the document structure as given. If the desired OBFL structure can not be accomplished purely with CSS, a pre-processing step is required. I haven't found an elegant solution for this problem. Maybe it's just something we need to live with. There are other parts of OBFL that are not very well suited for CSS, like the way the volume breaking is controlled (the keep-volume-priority properties). The fact that this will complicate my CSS-to-OBFL implementation is not really a reason to dismiss a design. It's just a remark.

Finally a suggestion to fix an ambiguity in the specification:

Every toc-entry refers to a block through attribute ref-id. If Dotify decides to apply a volume break such that the block is split accross several volumes, then toc-text-resumed is applied in all those volumes except the first one.

In OBFL we should state whether in case multiple nested blocks that are referenced by toc-entrys are split across volumes, all the corresponding toc-text-resumed are inserted in the new volume, or only the toc-text-resumed corresponding to the innermost block. For the strength of the design I think it would be nice if one could control this. There are various ways to achieve this, but letting it be determined by the document structure sounds the most logical. In other words, if you don't want multiple toc-text-resumed you need to make sure the referenced blocks are not nested.

PaulRambags commented 4 years ago

I would insert at most one toc-text-resumed.

It is the structure of the toc-entrys that determines which toc-text-resumed is inserted, not the structure of the corresponding blocks. So there is no need of a restriction on the block structure. The innermost non-empty toc-text-resumed is inserted, if it exists.

Every toc-entry refers to a block. The information that I need is:

bertfrees commented 4 years ago

It is the structure of the toc-entrys that determines which toc-text-resumed is inserted, not the structure of the corresponding blocks. So there is no need of a restriction on the block structure.

Well, the reason I made the suggestion is because the scope of the toc-entrys is already determined by the document structure. The user needs to make sure that blocks are present at the desired locations. By letting one aspect of the scope, namely which toc-text-resumed should "win" when there are multiple options, be determined by the structure of the table-of-contents, we would create a mixed situation that is less logical.

Another important reason for keeping the structure of the table-of-contents separate from the scope of the toc-entrys is because the structure is already determining for the layout of the table-of-contents itself.

Actually, after giving it some more thought I don't even think that we should allow multiple toc-text-resumed in case of nested blocks. I realize now that, if there would be a need to repeat other headings in addition to the most recent one, it would be much simpler and more flexible to just repeat that content inside the toc-text-resumed element.

Still, it's important to document clearly which toc-text-resumed are selected in case of doubt. You said:

The innermost non-empty toc-text-resumed is inserted, if it exists.

This is still ambiguous because it is quite possible that there are multiple toc-entrys that are themselves not nested, but reference blocks that are nested. In such cases you can either say:

I think the last option makes the most sense.

Also, whether a toc-text-resumed is empty or not shouldn't have an influence on whether it is selected. Making a toc-text-resumed empty can be a way to insert nothing (if another non-empty toc-text-resumed would otherwise be selected). Probably not a use case that we'll ever encounter, but still, important from a design point of view.

PaulRambags commented 4 years ago

I would like to illustrate my idea with two examples. For readability I use plain text instead of braille characters.

Example 1 Suppose we have the following toc structure:

toc-entry ref="h_1" toc-text="Chapter 1" toc-text-resumed="Chapter 1 continued"
    toc-entry ref="h_1_1" toc-text="Chapter 1.1" toc-text-resumed="Chapter 1.1 continued"
    toc-entry ref="h_1_2" toc-text="Chapter 1.2"
toc-entry ref="h_2" toc-text="Chapter 2" toc-text-resumed="Chapter 2 continued"

For every toc-entry, the CrossReferenceHandler tells us on which volume number the corresponding block starts. For instance, the volume number of the block of entry h_1_2 is crh.getVolumeNumber("h_1_2"). Suppose we also know whether or not such a block starts at the beginning of the volume's body. For instance crh.isAtStartOfVolumeBody("h_1_2") (Boolean) is true when the block that h_1_2 refers to is at the start of the volume contents, and false otherwise. This functionality has to be implemented yet.

Now we can determine by looking at the volume numbers whether a volume break occured, and if so, where:

  1. before the start of the h_1 block
  2. in between the start of blocks h_1 and h_1_1
  3. in between the start of blocks h_1_1 and h_1_2
  4. in between the start of blocks h_1_2 and h_2.

Crucial in this is that the toc-structure corresponds to the block-structure, which is required (see https://braillespecs.github.io/obfl/obfl-specification.html#L735).

Now, suppose a volume break occurs before the block of toc-entry h_2. Then, the algorithm would work as follows:

If crh.isAtStartOfVolumeBody("h_2") then no toc-text-resumed is applied in the second volume. Otherwise this toc-text-resumed is applied in the second volume:

  1. none
  2. "Chapter 1 continued"
  3. "Chapter 1.1 continued"
  4. "Chapter 1 continued" (there is no toc-text-resumed, so we fall back to the parent toc-entry)

Example 2 This example is to illustrate that the above idea works irrespective of the block structure. Suppose we have the following toc structure:

toc-entry ref="h_1" toc-text="Chapter 1" toc-text-resumed="Chapter 1 continued"
toc-entry ref="h_2" toc-text="Chapter 2" toc-text-resumed="Chapter 2 continued"

The body of the book consists of four blocks in a sequence, and the second block - which is not referred to in the toc - has a complex structure and is so large that a volume break occurs within it:

<block id="h_1">Chapter 1</block>
<block>Contents of first chapter
    <block>which may have a complex structure</block>
    <block>
        <block>in the sense that it has several
            <block>nested blocks</block>
        </block>
        <block>and it is so large that a volume break</block>
        <block>occurs within it</block>
    </block>
</block>
<block id="h_2">Chapter 2</block>
<block>Contents of second chapter</block>

The algorithm would detect that a volume break occured in between blocks h_1 and h_2 because crh.getVolumeNumber("h_1") = 1 and crh.getVolumeNumber("h_2") = 2. Then, if crh.isAtStartOfVolumeBody("h_2") no text-toc-resumed is applied. Otherwise, "Chapter 1 continued" is applied in the second volume. The second block has a complex structure, but the algorithm still works without having to inspect that structure.

kalaspuffar commented 4 years ago

Hi @PaulRambags and @bertfrees

I know that naming is important and a hard issue to solve. I've not looked into the issue more than reading this issue, so there might be some nuance that I've not grasped, but my suggestion would be to have a flag if a section is already defined and then handle the text in styles or post-processing. With just a flag, you convey the same information without deciding on how the output should be formed.

Suggestion 1:

toc-entry ref="h_1" toc-text="Chapter 1" toc-entry-resumed
toc-entry ref="h_2" toc-text="Chapter 2" toc-entry-resumed

Suggestion 2:

toc-entry ref="h_1" toc-text="Chapter 1" toc-entry-continued
toc-entry ref="h_2" toc-text="Chapter 2" toc-entry-continued

Suggestion 3:

toc-entry ref="h_1" toc-text="Chapter 1" predefined
toc-entry ref="h_2" toc-text="Chapter 2" predefined

If I missed something, then inform me and continue with the design purposed.

Best regards Daniel

bertfrees commented 4 years ago

@PaulRambags It's funny that you think this is your idea, because I've been saying this from the beginning :-). Read my emails from 11 September 2018, 22:51 ("OBFL and Chapters (continued)") and 23 July 2019, 15:07 ("Vervolg van hoofdstuk") again. I also tried to explain this when I was in Grave the last time and we were sitting in your office writing on the white board, remember?

But anyway, it's good that you bring it up again, because I eventually dismissed the idea. Not sure anymore exactly why, I think because I thought the other solution gave us somewhat more control over the scope of toc entries (e.g. making the scope of an entry end sooner, or having overlapping scopes). But thanks to new insights I'm again all in favor for this idea. Great.

@kalaspuffar I don't get what you are proposing. Could you elaborate?

PaulRambags commented 4 years ago

@bertfrees You're right, I should not have used the word "my" in "my idea". :-) I'm glad that you approve of the proposed approach.

kalaspuffar commented 4 years ago

Hi @bertfrees and @PaulRambags

I got an email from Paul explaining the situation and I might have missed the point totally.

What I thought we were talking about was adding elements that look like this

<toc-entry ref="h_1" toc-text="Chapter 1" toc-text-resumed="Chapter 1 continued"/>

I've now realized you were talking about a structure more like this:

<toc-entry>
   <ref>h_1</ref>
   <toc-text>Chapter 1</toc-text>
   <toc-text-resumed>Chapter 1 continued<toc-text-resumed>
</toc-entry>

And my suggestion was more inline of:

<toc-entry ref="h_1" continued="true">Chapter 1</toc-entry>

Best regards Daniel

kalaspuffar commented 4 years ago

Hi @PaulRambags and @bertfrees.

We have talked a bit this morning and we propose the following. Below you will see two examples on how to apply the continued concept on two entries.

<toc-entry ref="h_1"><span use-when="($continued)">Continuation of </span>Chapter 1</toc-entry>
<toc-entry ref="h_1">Chapter 1<span use-when="($continued)"> continued</span></toc-entry>

And for a full example taken from a book, it could look something like this:

<toc-entry ref-id="d5e177" block-indent="1" text-indent="2" keep="page"><span use-when="($continued)">Continuation of </span>2. Exodus (281) <leader position="100%" align="right" pattern="."/> <page-number ref-id="d5e177"/></toc-entry>

Best regards Daniel

bertfrees commented 4 years ago

See PR for OBFL: https://github.com/mtmse/obfl/pull/4