Open gwyndaf opened 3 months ago
I once experimented with section styles. When you open a section e.g. {start_of_bridge}
ChordPro would look for a config setting pdf.section.style
and use this for font, size, colour.
pdf.section.style {
bridge {
font: serif
size: 12
color: blue
}
}
It was stalled for some reason, I don't remember why.
Your proposal sounds nice and logical. Being able to define a style as a set of properties (font/size/color/background/spacing) and then automatically apply the style to each section of the same name, or use a style=
property to designate the style. Shouldn't be that hard to implement.
While pdf.fonts
could be used for this purpose I wonder whether it is better to separate the font from the style. The term 'font' is already very overloaded.
If it also includes attributes like line spacing, style would certainly be a more accurate term than font and, as you say, font is already doing a lot of work. Treating styles as a slightly separate area of functionality might also make it easier to experiment with in development without affecting existing spacing
and fonts
functionality.
There's maybe a question of what else might potentially be included in a style. If we consider chorus
as a model, we've also got section-related attributes like indent
and bar
. I don't know whether they should be defined in the style or in the section. If I consider WP/DTP parallels, things like indent are generally included in style definitions (I'm cautious about encouraging users to think ChordPro is a WP/DTP tool but, if there are similar concepts, maybe it's clearer for users if their scope is similar).
And should styles include typographic nuances currently available only through markup but not fonts
settings: things like rise
or underline_color
, for instance? I'm not necessarily advocating their inclusion, but simply that the styles mechanism is flexible enough to accommodate them in future, if necessary. This also makes me wonder whether character-level setting names should be consistent with markup: for instance, using face
rather than font
(which may also remove some ambiguity around 'font').
That is, it seems like there are potentially three(?) categories of style information, section-level, line-level and character-level, so I suppose the relevant style settings would need to be parsed and 'sent to' the relevant area of processing.
Your earlier section style example would certainly make sense for my suggested simple approach 1). However, it ties styles closely to sections, which could be limiting. I wonder if a slight change might leave the door open to a more flexible approach in future, like the more flexible/powerful approach 2). That is, if we change around the relationship, so style
is an attribute of each section
, for instance:
pdf.section.bridge {
style {
font: serif
size: 12
color: blue
}
indent: 30
}
That might simplify a future shift to something like
pdf.styles {
bridge {
font: serif
size: 12
color: blue
spacing: 1.1
indent: 30
underline_color: #008800
}
}
pdf.section.bridge {
style: bridge
}
which could then also be used ad hoc like {start_of_prechorus: style=bridge}
.
Possibly that same style could also be applied to specific characters (i.e. not section- or -line-level attributes like indent
or spacing
):
{start_of_chorus}
Some [C] regular chorus [G]stuff
Some <sty=bridge>special stuff</sty>
{end_of_chorus}
I'm probably inventing some strange and hypothetical scenarios, not necessarily as actual use cases, but simply to help conceive an initial approach to styles that allows maximum flexibility for future refinement.
We're moving towards CSS, aren't we? Well, why not...
A ChordPro section corresponds to a <div>
(display:block), and a textual span to a <span>
(display:inline).
Properties for <span>
:
Properties for <div>
: all <span>
properties, plus
A default chorus would be something like margin-left:-8; padding-left:8; border-left: 1px solid foreground
.
The default class for a section is the section name; the following are equivalent:
{start_of_bridge}
{start_of_bridge class="bridge"}
style
is then available for additional properties, e.g.
{start_of_bridge class="fancy" style="font-weight:bold"}
While this may seem a bit overkill at first, it has the advantage that it elegantly separates the appearance from the other configs, and many people will have already some basic experience with CSS.
Actually, when I started the ChordPro rewrite, my intention was to go HTML+CSS. Unfortunately there were (and, AFAIK, are) no decent tools to produce good PDF from HTML+CSS. ('good' meaning handling running headings and footers, toc generation, etc.)
Ah, interesting idea. I hadn't really considered any particular syntax, and just assumed something like the the existing, for consistency. Mainly my thought was the general conceptual model of styles, as used in wordprocessing and DTP applications and, of course, CSS, which I hadn't considered.
Doesn't seem so much overkill as smart adoption of a familiar, mature, comprehensive and rigorous approach to styles, which many minds have already spent years considering, developing, and using. Even if initial ChordPro implementation is limited, as per your suggested <span>
and <div>
properties, the standards are there for any future growth.
I like your idea of that sections default to the class
of the same name (if defined): it helps keep the song source clean, readable and portable.
Separating appearance (into a separate CSS or similar file?) makes sense. In fact, my own multiple configs can be roughly categorised as core, instrument, page layout and typography, which get combined in different ways for different purposes.
Perhaps another advantage/possibility: if, at some point, it seems useful or sensible to build a visual config editor into the GUI, there might be existing tools/code that can do that (or be adapted) for CSS.
Good point that CSS is fundamentally intended for on-screen/continuous output, rather than page-based print/PDF, so concepts like header/footer are alien. My HTML/CSS knowledge is rusty, but I think it at least supports pt
sizes (not just px
), so would support suitable measurement units for physical/page use (I've dealt with many designers who don't know their px
from their pt
!).
Might an intermediate approach be to support CSS syntax for body layout and typography, but retain existing page layout functionality like paper size, margins and pdf.formats
: that already supports markup, so is there any reason it couldn't also support <span class=... >
styles?
That way, perhaps existing PDF layout processes could maybe be retained, and styles (even if in CSS syntax) somehow translated into the equivalent spacing
and font
values?
Good points!
CSS is fundamentally intended for on-screen/continuous output, rather than page-based print/PDF.
This is a common misconception. CSS3 has several selectors and property settings to deal with printed content. See e.g. src/ChordPro/lib/ChordPro/res/styles/print.css
.
It is just that noone seems to feel like supporting these...
HTML is an relevant target anyway, since it allow for partial processing (e.g. process a section only). This may be interesting for live-updating editors.
Also (not related): A section can contain lyrics lines so we need to be able to specify styles for both the lyrics and the chords.
Interesting point about styles to change chord appearance by section. My thinking arose largely from what's currently possible for chorus
, and making similar format control available for other/arbitrary sections, and that's largely about lyrics format/layout.
That said, I use mostly inline chords, so their layout just follows lyrics. With above-line chords, I suppose their layout already does change, e.g. if chorus is indented.
I wonder if this raises questions about how things like inline-chords
and (maybe?) chord-formats
might be handled in a CSS model, if there was provision for the appearance of chords to vary by section.
For example, I currently have some subtle styling of chord delimiters for inline chords
(with base fonts.chord.color : #008800
):
"inline-chords" : "<span weight=regular color=#228822>(</span>%s<span weight=regular color=#228822>)</span>",
So, I imagine each section style might need to allow for inline-chords
(or equivalent) functionality. I wonder if this also has implications for 'conditional' chord formatting, for optional or passing chords based on suffixes like [Gm*]
(as discussed in #352)
Thanks for the suggestions. I now remember:
It was stalled for some reason, I don't remember why.
I realised that in the end, a section would become a mini-song (cf. the LaTeX minipage), complete with its own config. That was going a bit too far.
In practice, I think people will want the option for a section to have just a different font or colour. So it is sufficient to support the set of properties enumerated in https://github.com/ChordPro/chordpro/issues/404#issuecomment-2272971571.
div.bridge: {
font-size: 120%;
}
This will affect all content (i.e, lyrics and fonts). To change only chord properties we can use a selector:
div.bridge chords: {
font-size: 10;
}
I agree that it's enough just to provide control over just a limited number of chord appearance properties. Your work on chord-formats
is really useful, and it seems counter-productive to compromise/break that for implementing styles.
I see a couple of questions following from .chords
styles:
1) For inline chords, should bridge.chords
affect only the chord (%s
value) or the whole inline-chords
value?
I think the latter is preferable for immediate practical purposes. For instance, I currently use variations of green for chords and delimiters. If a chord colour is varied to blue in bridge.chords
, it's probably more sensible that both chord and delimiters are made blue, rather than blue chords within green delimiters. However, I think it's important to retain the current approach to the default inline-chords
, which lets me do some nice things :)
2) Should annotations also follow .chords
formatting?
I don't think I have a strong view. I'm guessing that they'd vary from fonts.annotations
according to what's defined in div.bridge.chords
. So, with the example above, annotations would turn blue, like chords themselves. Maybe an annotations
selector could be useful in future, but seems unnecessary complication right now.
Potentially, in future, more subtle colour control could overcome some short-term compromises. For example, my inline chord delimiters are the chord colour but a bit lighter, while annotations are a darker shade of the chord colour. Potentially, those 'lighter' and 'darker' adjustments could be part of the default config (or base style), so they're retained when a different colour hue is applied. This is my thinking behind #340, although I realise that's dependent on PDF::API2
functionality, so not an immediate prospect.
This may be a good opportunity to remove some of the font overloading.
div.bridge chord
affects chords only. div.bridge annotation
affects annotations only. In either case, this is the whole formatting string, just as it is now.
div.bridge chord[inline]
affects inline chords only. div.bridge annotation[inline]
affects inline annotations only.
Hmm. Now it looks as if inline is a property... Well, why not:
div.bridge chord#foo { inline: "{{%s}}" }
with
{start_of_bridge}
[A]Hello, [<span id="foo">B</span>]World
{end_of_bridge}
This would produce
A
Hello {{B}}World
Nope, let's not do that ☺. Maybe just:
div.bridge chord { inline: "{{%s}}" }
with
[A]Hello [B]Hello
{start_of_bridge}
[A]Hello, [B]World
{end_of_bridge}
This would produce
A B
Hello Hello
{{A}}Hello {{B}}World
But that's for later.
Can you confirm #399? Then I can fix the spreads and roll out 6.060.
Possible enhancement for the longer term.
Rationale
1) It's possible to use custom environments, such as
{start_of_bridge}
or{start_of_wittyrap}
but, I believe, not possible to define how they should look in configs, because existingpdf.spacing
andpdf.fonts
sections are available only for standard song elements, not custom ones.2) Used in markup, styles could help make character-level formatting simpler, more consistent and clearer in code. For instance, backing vocals might often be on the same line as lyrics, so must(?) be formatted using markup, not directive.
3)
pdf.spacing
andpdf.fonts
item names aren't always consistent (e.g.lyrics
andtext
). This might be an opportunity to rationalise that.Possible implementations
1) Basic extension of current functionality. In
pdf.fonts
, allow arbitrary names to be created, such aspdf.fonts.bridge
orpdf.fonts.footnote
. When, say,{start_of_bridge}
is used, ChordPro usespdf.fonts.bridge
if defined; if not defined, falls back to ? maybefonts.text
? Maybe there's a need to specify line spacing but - as that's relative to font size - it might be unnecessary, and could overcomplicate this as a 'basic' approach. Even if not defineable, it should be clear which spacing setting gets used by customs styles (maybelyrics
?).2) Independent styles, which aren't hard-wired to existing song elements, but could be linked somehow. Possibly this might be an opportunity to consolidate typography settings in one place, e.g. both line spacing and font spec under the same item name. When referenced in a line-level context (e.g. a directive like
{start_of_chorus: style=rousing}
), all settings get applied; when referenced in a character-level context (e.g. markup), only font-specific settings are applied and line spacing ignored: for instance, for backing vocals, something like<span style=bv>
,<sty=bv>
or even<bv>
to reference abv
style. In my own usage, I currently use the<i>
short tag for BVs (because it's short and clean within the song source), but need to use preprocessor to convert into a more specific format (italic and grey). And anything that needs preprocessor handling seems like a good candidate for an enhancement! :)I'm conscious that this thinking reflects only PDF usage. If it involves a major enhancement, I guess the ideal approach would be flexible enough to serve other output formats, such as HTML and LaTeX.
I'm sure the second of these in particular would need much more thought and work, so just raising this as a possible item for future consideration.