Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support more book divisions #119

Merged
merged 7 commits into from
Jan 17, 2025
Next Next commit
feat(classes): Support frontmatter/mainmatter/backmatter divisions
Omikhleia authored and Didier Willis committed Jan 15, 2025
commit afb1d2a3c1daf81dc0ed51e89300a93354759525
70 changes: 67 additions & 3 deletions classes/resilient/book.lua
Original file line number Diff line number Diff line change
@@ -20,10 +20,17 @@ SILE.scratch.book.headers = {
none = true
}

local DIVISIONNAME = {
"frontmatter",
"mainmatter",
"backmatter"
}

-- CLASS DEFINITION

function class:_init (options)
base._init(self, options)
self.resilientState = {}

self:loadPackage("resilient.sectioning")
self:loadPackage("masters")
@@ -86,6 +93,7 @@ function class:_init (options)
-- Package "folio" is loaded by the plain class.
self:registerCommand("foliostyle", function (_, content)
local styleName = SILE.documentState.documentClass:oddPage() and "folio-odd" or "folio-even"
local division = self.resilientState.division or 2
SILE.call("style:apply:paragraph", { name = styleName }, {
-- Ensure proper baseline alignment with a strut rule.
-- The baseline placement depends on the line output algorithm, and we cannot
@@ -94,7 +102,10 @@ function class:_init (options)
-- aligned folios, but the 1 is smaller than the 6 and 7, the former ascends above,
-- and the latter descends below the baseline).
createCommand("strut", { method = "rule"}),
subContent(content)
createCommand("style:apply:number", {
name = "folio-" .. DIVISIONNAME[division],
text = SU.ast.contentToString(content),
})
})
end)

@@ -202,6 +213,18 @@ end
function class:registerStyles ()
base.registerStyles(self)

-- Front, main, back matter
local divisionFolio = {
frontmatter = "roman",
}
for _, name in ipairs(DIVISIONNAME) do
self:registerStyle("folio-" .. name, {}, {
numbering = {
display = divisionFolio[name] or "arabic"
}
})
end

-- Sectioning styles
self:registerStyle("sectioning-base", {}, {
paragraph = { before = { indent = false },
@@ -562,6 +585,42 @@ function class:registerCommands ()
end
end, "Text to appear on the top odd pages.")

-- front/main/back matter

self:registerCommand("internal:division", function (options, _)
local division = SU.required(options, "division", "internal:division")
-- Always start on an odd page, so as to be consistent with the folio numbering
-- in case it is reset.
SILE.call("open-on-odd-page")
self.resilientState.division = division
-- Previous section titles (in technical mode) or chapter title (in novel mode)
-- is no longer valid (and in none mode, it's not valid anyway).
SILE.scratch.headers.odd = nil
if self.headers == "technical" then
-- In novel mode, the book title is in the even header, and is still valid
-- So we don't reset it.
-- But in technical mode, even headers contain the current chapter title,
-- invalid upon a new part.
SILE.scratch.headers.even = nil
end
-- Reset folio counter if needed (i.e. on display format change)
local current = self:getCounter("folio")
local folioSty = self:resolveStyle("folio-" .. DIVISIONNAME[division])
local display = folioSty.numbering and folioSty.numbering.display or "arabic"
if current.display ~= display then
SILE.call("set-counter", { id = "folio", display = display, value = 1 })
end
end)

for div, name in ipairs(DIVISIONNAME) do
self:registerCommand(name, function (_, content)
if self.resilientState.division and self.resilientState.division >= div then
SU.error("\\" .. name .. " is not valid after a " .. DIVISIONNAME[self.resilientState.division])
end
SILE.call("internal:division", { division = div }, content)
end, "Switch to " .. DIVISIONNAME[div] .. " division.")
end

-- Sectioning hooks and commands

self:registerCommand("sectioning:part:hook", function (options, _)
@@ -615,11 +674,17 @@ function class:registerCommands ()
end, "Applies section hooks (footers and headers, etc.)")

self:registerCommand("part", function (options, content)
if self.resilientState.division and self.resilientState.division ~= 2 then
options.numbering = false
end
options.style = "sectioning-part"
SILE.call("sectioning", options, content)
end, "Begin a new part.")

self:registerCommand("chapter", function (options, content)
if self.resilientState.division and self.resilientState.division ~= 2 then
options.numbering = false
end
options.style = "sectioning-chapter"
SILE.call("sectioning", options, content)
end, "Begin a new chapter.")
@@ -823,8 +888,7 @@ function class:registerCommands ()
-- Kind of a hack dues to restrictions with frame parsers.
layout:setPaperHack(SILE.documentState.paperSize[1], SILE.documentState.paperSize[2])

SILE.call("supereject")
SILE.typesetter:leaveHmode()
SILE.call("open-on-any-page")

local oddFrameset, evenFrameset = layout:frameset()
self:defineMaster({
39 changes: 37 additions & 2 deletions examples/manual-classes/classes.sil
Original file line number Diff line number Diff line change
@@ -291,7 +291,7 @@ The class also defines two commands for manipulating the page headers.
\begin{row}
\cell[valign=top]{\autodoc:command{\odd-tracked-header{<content>}}}
\cell[valign=top]{Registers the content to be used in odd running headers, tracked.}
\end{row}
\end{row}
\end{ptable}
\caption{Commands for manipulating page headers.}
\end{table}
@@ -313,6 +313,39 @@ The environment relies on the same-named style for its styling and on the \autod

The environment also accepts a \autodoc:parameter{variant} option, to switch to an alternate style, assumed to be named \code{blockquote-⟨\em{variant}⟩}.

\section{Front, main and back divisions}

The class supports the standard \autodoc:command{\frontmatter}, \autodoc:command{\mainmatter} and \autodoc:command{\backmatter} commands to switch between the different higher-level divisions of the document.
Obviously, these commands can only occur once in the document, and in the order given above.
They start a new page, and influence the style of folios.

\begin{table}
\begin[cols=40%fw 50%fw, header=true]{ptable}
\begin[background=#eee]{row}
\cell[valign=top]{Style}
\cell[valign=top]{Description}
\end{row}
\begin{row}
\cell[valign=top]{\code{folio-frontmatter}}
\cell[valign=top]{Numbering style applied to folios in the front matter.}
\end{row}
\begin{row}
\cell[valign=top]{\code{folio-mainmatter}}
\cell[valign=top]{Numbering style applied to folios in the main matter.}
\end{row}
\begin{row}
\cell[valign=top]{\code{folio-backmatter}}
\cell[valign=top]{Numbering style applied to folios in the back matter.}
\end{row}
\end{ptable}
\caption{Styles used for folios in different document divisions.}
\end{table}

Books not using these divisions assume "main" matter by default.
In the "front" and "back" matter divisions, parts and chapters are never numbered.
Not that this is not a configurable style decision, but the very definition of these divisions.
In "main" matter, they are numbered by default, although this can be changed either on the sectioning command itself, or globally with adequate styles.

\section{Other features}

The footnotes are based on the \autodoc:package{resilient.footnotes} package and therefore have the
@@ -329,7 +362,9 @@ available.
\medskip
A few layout-related commands are also provided.

The \autodoc:command{\layout[layout=<layout spec>]} command inserts a page break and changes the page layout from that point. An optional \autodoc:parameter{offset=<dimen>} may be specified to also alter the binding offset. By default, the global offset (that is, as possibly defined via the corresponding class option) is used.
The \autodoc:command{\layout[layout=<layout spec>]} command inserts a page break if needed, and changes the page layout from that point.
An optional \autodoc:parameter{offset=<dimen>} may be specified to also alter the binding offset.
By default, the global offset (that is, as possibly defined via the corresponding class option) is used.

Mostly intended for documentation, the \autodoc:command{\showlayout[layout=<layout spec>, papersize=<paper spec>]} command outputs an image representing the selected page layout and paper size.
Optional parameters are \autodoc:parameter{offset=<dimen>} for the binding offset (0, that is no offset, by default), \autodoc:parameter{ratio=<number>} for the image down-scaling (dividing the paper size by the specified amount, 6.5 by default), and \autodoc:parameter{rough=<boolean>} (false by default).
30 changes: 22 additions & 8 deletions examples/manual-styling/advanced/folio.md
Original file line number Diff line number Diff line change
@@ -22,10 +22,8 @@ folio-odd:
indent: false
```

That common parent style is where we would ideally define the font, for instance
to use old-style numbering. It is also where we can define the numbering format.
Robert Bringhurst says: "It is usual to set folios in the text size"---so we won't
change the font size.
That common parent style is where we would ideally define the font, for instance to use old-style numbering.
Robert Bringhurst says: "It is usual to set folios in the text size"---so we won't change the font size.

```yaml
folio-base:
@@ -36,7 +34,23 @@ folio-base:
display: "arabic"
```

::: {custom-style="admon"}
Frontmatter / mainmatter / backmatter sections are not implement yet.
So for now, the above only documents the "mainmatter" general styling.
:::
The numbering format is defined in another set of numbering styles.
The usual settings is to have roman numbers in the front matter, and arabic numbers in the main and back matters.

```yaml
folio-frontmatter:
style:
numbering:
display: "roman"
folio-mainmatter:
style:
numbering:
display: "arabic"
folio-backmatter:
style:
numbering:
display: "arabic"
```

In books without these high-level divisions, `folio-mainmatter` is implied for the whole document.
As all of these are numbering styles, you can also extend them further, would you want to style the page numbers differently in these divisions.
13 changes: 4 additions & 9 deletions examples/manual-styling/advanced/intro.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
# Advanced styling

Having read the previous chapter, you should now know how to edit styles and
modify them at your convenience. Some of the styles used by resilient collection
of classes and packages, however, are probably worth being depicted with more
details.
Having read the previous chapter, you should now know how to edit styles and modify them at your convenience.
Some of the styles used by the resilient collection of classes and packages, however, are probably worth being depicted with more details.

The aim of this chapter is to present these advanced use cases, and possibly
to answer some frequently asked questions.
Please bear in remind, however, that the style inheritance model is very flexible,
and that you can possibly modify the style hierarchy to make it quite different
from the default setup.
The aim of this chapter is to present these advanced use cases, and possibly to answer some frequently asked questions.
Please bear in remind, however, that the style inheritance model is very flexible, and that you can possibly modify the style hierarchy to make it quite different from the default setup.
18 changes: 18 additions & 0 deletions examples/sile-resilient-manual-styles.yml
Original file line number Diff line number Diff line change
@@ -297,6 +297,12 @@ figure-caption-ref-number:
before:
text: "fig. "

folio-backmatter:
origin: "resilient.book"
style:
numbering:
display: "arabic"

folio-base:
origin: "resilient.book"
style:
@@ -312,6 +318,18 @@ folio-even:
before:
indent: false

folio-frontmatter:
origin: "resilient.book"
style:
numbering:
display: "roman"

folio-mainmatter:
origin: "resilient.book"
style:
numbering:
display: "arabic"

folio-odd:
inherit: "folio-base"
origin: "resilient.book"