Makes each copy of an SVG in a document independent of the other copies
The document holds each slide three or more times: in the present view, on each page of the handout view and in the menu. A copy of an SVG then needs its own ids and its own style rules, for two causes:
- A browser resolves a reference such as
url(#fill)to the first element of the document with thatid. That element can be in a view that the browser does not show, and a gradient, a clip or a mask in a hidden view does not paint. - A
<style>element in an inline SVG applies to the whole document. Two files with the same class names then change the colors of each other.
number/2 puts the number of the copy after each id of the SVG, and it
puts the same number into each url(#id), each href="#id" and each #id
selector of a <style>. It makes a map from each old id to its new id, and
it changes the text in one pass, so an id such as g1-2 does not change
two times. Then it limits each rule of each <style> to the copy: the root
svg element gets data-svg-copy with the number, and the subject of each
selector gets :where([data-svg-copy="N"], [data-svg-copy="N"] *). The
:where adds no specificity, so the rules of the file keep their order
against the rules of the theme.
A rule in @media, @supports, @container or @layer gets the same
change. Other at-rules, such as @keyframes and @font-face, stay as they
are.
Expresso.Element.Diagram, Expresso.Element.Icon,
Expresso.Element.TextArea and Expresso.Element.Item use this module, and
Expresso.Copies.next/0 gives the number.
Summary
Functions
Number the copy of an SVG with the next number of Expresso.Copies
Number each SVG of an HTML text with its own number
Put a number into each id, each reference and each style rule of an SVG
Functions
Number the copy of an SVG with the next number of Expresso.Copies
An SVG with no id and no <style> stays as it is, and it takes no number.
iex> Expresso.SvgCopy.copy(~s(<svg viewBox="0 0 1 1"><path d="M0 0h1"/></svg>))
~s(<svg viewBox="0 0 1 1"><path d="M0 0h1"/></svg>)
Number each SVG of an HTML text with its own number
A text area and an item can hold more than one inline icon, and two icons with the same file must have different ids.
@spec number(String.t(), pos_integer()) :: String.t()
Put a number into each id, each reference and each style rule of an SVG
iex> Expresso.SvgCopy.number(~s|<svg><linearGradient id="g1"/><linearGradient id="g1-2"/><rect fill="url(#g1-2)"/></svg>|, 2)
~s|<svg><linearGradient id="g1-2"/><linearGradient id="g1-2-2"/><rect fill="url(#g1-2-2)"/></svg>|
iex> Expresso.SvgCopy.number(~s(<svg id="s"><style>#s .a, b::before{fill:red}</style></svg>), 3)
~s|<svg data-svg-copy="3" id="s-3"><style>#s-3 .a:where([data-svg-copy="3"], [data-svg-copy="3"] *), b:where([data-svg-copy="3"], [data-svg-copy="3"] *)::before{fill:red}</style></svg>|