Closed Conal-Tuohy closed 3 years ago
One approach could be to translate the CSS selector syntax to equivalent XPath, and add an XProc step which processes the rendition[@selector]
elements; evaluates the XPath expressions and explicitly sets the @rendition
value of each matching element to refer to the rendition
element's @xml:id
.
go ahead with universal selector (*), first-child, last-child, id, and attribute selectors, child, descendant combinators
also added the following-sibling (~
) and next-sibling (+
) combinators
I finished the task, taking into account the specificity of the rendition/@selector
selectors.
What happens in the HTML is that the various TEI rendition
elements are rendered as CSS blocks with a class selector, and the various HTML elements have class attribute values based on the @rendition
attribute of the TEI element which was their source.
e.g.
<rendition xml:id="example">
font-style: italic;
</rendition>
produces CSS in the HTML page:
.rendition-example {
font-style: italic;
}
and a TEI paragraph like so:
<p rendition="#example">this should be in italics</p>
ends up as an HTML paragraph something like:
<p class="rendition-example">this should be in italics</p>
In order for these "class-based" selectors to respect the priority ordering of the selectors specified in the TEI, they just need to be listed in ascending order of specificity in the CSS stylesheet in the HTML, as later ones override the earlier ones.
So to achieve that, I've made it so the selector-evaluation stylesheet also sorts the rendition
elements in the same order. The stylesheet removes the original rendition[@selector]
elements and outputs new versions, outputting them at the start of the tagsDecl
in ascending order of specificity (so that the highest priority ones come last), and before any rendition
elements which didn't have a selector (which the stylesheet leaves alone).
A rendition
element in the source may actual contain several selectors in its @selector
attribute (delimited with commas). Because those selectors may have different specificity, the same rendition
styles may need to appear in multiple places within the priority order, so in those "multi-selector" cases there will be more of these "generated" rendition
elements than there were "source" rendition
elements. i.e. if a source rendition
element has a @selector
containing a general and also a very specific selector, then that will produce two rendition
elements, one at the start of the list of rendition
elements, and another at the end.
In 002dc0ee8e94a24f08493db9bc2274098f22ba67 I carefully read through the stylesheet and fixed up a bunch of misleading comments (mostly copy and paste errors) and a couple of minor logic errors; failing to always entirely deduplicate the list of @rendition
attributes when they are modified, and failing to copy rendition[@selector][@xml:id]
elements which might actually have been referred to by a @rendition
.
Added support for the :lang
pseudo-class, e.g. quote:lang(la)
will now match Latin quotes, even if the xml:lang='la'
tag is on an ancestor element of the quote
element, where quote[@lang='la']
will not serve the purpose.
Added support for :only-child
alongside the existing :first-child
and :last-child
(for completeness), and also added support for :first-of-type
, :last-of-type
, and :only-of-type
pseudo-classes, which I think are likely to be better choices than :first-child
etc in most cases, because e.g. in the poem below, l:last-of-type
will match the last line, where l:last-child
will not match anything.
<lg>
<l>line one</l>
<l>line two</l>
<l>line three</l>
<note>that's the end of the poem</note>
<lg>
Currently
rendition
elements can be associated with transcriptional elements in two ways:<p rendition="#foo-rendition">
tagUsage
element associating a rendition with a type of transcriptional element<tagUsage gi="p" rendition="#foo-rendition">
TEI has an additional and more flexible method for associating
rendition
elements with transcriptional elements, in which therendition
element points to the set of transcriptional elements to which it should reply, using a CSS selector<rendition selector="p:first-child">
Implementing this third method would require parsing and evaluating these CSS selectors, which is computationally a lot more work than the other methods require, but it can makes for much less clutter in the transcriptional markup, and provides a better separation of concerns than the first method, and has much more discriminatory power than the second method.