Der angebenen Downloaddatei wird, basierend auf deren Dateiendung, ein passendes Icon zugeordnet.
<svg
xmlns = "http://www.w3.org/2000/svg"
width = "48"
height = "48"
viewBox = "0 0 512 512"
>
<!-- Disk body -->
<polygon
id = "shape"
points = "0,0 512,0 512,512 50,512 0,462"
style = "fill: #0000ff;
fill-opacity: 1;
stroke: #000080;
stroke-width: 2;
stroke-opacity: 1;"
/>
<rect
id = "slideway"
width = "320"
height = "168"
x = "136"
y = "344"
style = "fill: #0000f0;
fill-opacity: 1;
stroke: #000000;
stroke-width: 2;
stroke-opacity: 1;"
/>
<rect
id = "slider"
width = "220"
height = "200"
x = "138"
y = "346"
rx = "20"
ry = "20"
style = "fill: #c0c0c0;
fill-opacity: 1;
stroke: none;"
/>
<rect
id = "slider slot"
width = "60"
height = "120"
x = "164"
y = "364"
style = "fill: #0000f0;
fill-opacity: 1;
stroke: none;"
/>
<!-- Disk label -->
<rect
id = "label"
width = "400"
height = "300"
x = "56"
y = "2"
style = "fill: #ffffff;
fill-opacity: 1;
stroke: #808080;
stroke-width: 2;
stroke-opacity: 1;"
/>
<line
id = "topmost label line"
x1 = "68"
y1 = "70"
x2 = "444"
y2 = "70"
style = "stroke: #000000;
stroke-opacity: 1;
stroke-width: 3;"
/>
<line
id = "mid label line (below the text)"
x1 = "68"
y1 = "230"
x2 = "444"
y2 = "230"
style = "stroke: #000000;
stroke-opacity: 1;
stroke-width: 3;"
/>
<line
id = "lowest label line"
x1 = "68"
y1 = "280"
x2 = "444"
y2 = "280"
style = "stroke: #000000;
stroke-opacity: 1;
stroke-width: 3;"
/>
<text
id = "label imprint"
x = "68"
y = "180"
style = "font-style: normal;
font-variant: normal;
font-weight: bold;
font-stretch: normal;
font-size: 7rem;
font-family: Work Sans, Helvetica, Tahoma, Geneva, Arial, sans-serif;
font-variant-ligatures: normal;
font-variant-caps: normal;
font-variant-numeric: normal;
font-feature-settings: normal;
text-align: start;
writing-mode: lr-tb;
text-anchor:start;"
>
<!-- Label text goes here, max. 5 glyphs, or 4 ems "MMMM"! -->
<!-- Attention: countrunes still gets the leading '.' if there is any! -->
<!-- This is why the '(none)' is given even if we one rune. -->
{{- $fext := path.Ext .Params.file -}}
{{- if gt (countrunes $fext) 1 -}}
<!-- Remember the very first rune is the '.'! So we take just 5 -->
<!-- runes as the file type. If more than those it will get -->
<!-- truncated to four runes plus the ellipsis -->
{{- if le (countrunes $fext) 6 -}}
{{- delimit (first 1 (findRE "[^(.)].{0,4}" $fext)) " " -}}
{{- else -}}
{{- delimit (first 1 (findRE "[^(.)].{0,3}" $fext)) " " -}}
… <!-- ellipsis -->
{{- end -}}
{{- else -}}
(none)
{{- end -}}
</text>
</svg>
Wie man sieht, ist das Icon als SVG definiert.
Zunächst wird das SVG eingeleitet:
<svg
xmlns = "http://www.w3.org/2000/svg"
width = "48"
height = "48"
viewBox = "0 0 512 512"
>
<svg>
zeigt dem Browser an, dass nun eine Grafikdefinition gemäß
SVG-Standard
folgt. Dabei werden im tag einige Attribute mitgegeben.
xmlns = "http://www.w3.org/2000/svg"
wäre, dem
SVG-Standard
folgend, gar nicht erforderlich. Beim Experimentieren mit Firefox (69.0.3) hat
sich allerdings gezeigt, dass ohne diese Zeile das SVG nicht erzeugt wird.
Schädlich ist es nicht und so bleibt es als “Browser-Workaround” im Script.
(Siehe eventuell unsere
Diskussion zum xmlns.)
width = "48"
legt die gewünschte Breite auf der Seite fest. Die Einheit ist
Pixel.
height = "48"
definiert baugleich die Höhe des Icons.
viewBox = "0 0 512 512"
hingegen gibt die Größe der Zeichenfläche an. Auf
diese Zeichenfläche werden gleich die einzelnen Elemente gezeichnet und
positioniert.
Als Icon soll eine stilisierte 3.5”-Diskette erscheinen. Der Grundkörper ist 5-seitig - zunächst ein Quadarat, bei dem links unten eine Ecke abgeschnitten ist. Der Grundkörper nutzt die Zeichenfläche voll aus.
<polygon
id = "shape"
points = "0,0 512,0 512,512 50,512 0,462"
style = "fill: #0000ff;
fill-opacity: 1;
stroke: #000080;
stroke-width: 2;
stroke-opacity: 1;"
/>
<polygon
leitet die Sequenz ein. Die Angabe einer id
ist optional, es geht
auch ohne. Hier wird sie als Orientierungshilfe verwendet, um die Teile besser
identifizieren zu können. points
definiert nun die Punktliste, die das
Polygon auf seinen Ecken trifft. Jeder Punkt besteht aus den Koordinaten
x,y
. Links oben im Ursprung (0,0
) beginnt der Umriss, geht horizontal nach
rechts oben (512,0
), von dort aus vertikal nach unten (512,512
- man
beachte das Vorzeichen der y-Richtung!) und wieder nach links, allerdings
nicht ganz bis zum Anschlag (50,512
). Von diesem Punkt aus geht es diagonal
zum Punkt 0,462
(462 = 512-50), das ergibt einen 45°-Winkel.
Der Polygonzug wird automatisch vom letzten angegeben Punkt zum Startpunkt
geschlossen.
style = ""
eröffnet die Formatierung bezüglich des Aussehens.
fill: #0000ff;
füllt das Polygon blau.
fill-opacity: 1;
sorgt für opaque Füllung (keine Transparenz).
stroke: #000080;
färbt den Rand des Polygons dunkelblau.
stroke-width: 2;
gibt die Breite des Randes vor.
stroke-opacity: 1;
entzieht auch dem Rand jede Transparenz.
Nachdem der Grundkörper definiert ist, folgen die weiteren Elemente:
<rect id = "slideway"
)<rect id = "slider"
) mir runden Ecken<rect id = "slider slot"
)<rect id = "label"
)<line id = "topmost label line"
),
(<line id = "mid label line (below the text)"
) und
(<line id = "lowest label line"
)<text id = "label imprint"
)Dabei werden die Elemente der Reihe nach “gezeichnet”, bei Überlappung werden
vorher definierte Elmente überdeckt. Gehen Element über die Grenzen des
viewport
hinaus, werden die betreffenden Teile abgeschnitten.
Die Finessen der einzelnen Zeichnungselemente (rect, line, text) beschreibt das w3schools-Tutorial. An dieser Stelle sei darauf verwiesen.
Als Beschriftung wird die Dateiendung des Download-Files verwendet. Schritt für Schritt:
{{- $fext := path.Ext .Params.file -}}
Der Dateiname wird durch .Params.file
angeliefert.
(path.Ext
) holt die Endung des Dateinamens (alles hinter und mit dem
letzten ‘.') dort heraus.
Die Dateiendung wird in der Variablen $fext
aufbewahrt.
Von der /ftpedia/2019/2019-3/ftpedia-2019-3.pdf
bliebe .pdf
übrig. Aber
die ft:pedien werden speziell und besonders behandelt.
Dateiendungen sind nun nicht auf exakt drei Zeichen festgelegt. Diesem Umstand
wird durch Fallunterscheidungen Rechnung getragen.
Zunächst wir mal nachgeschaut, ob es überhaupt eine Dateiendung gibt. Wenn ja
gibt es mehr als ein Zeichen. Man denke bitte an den Punkt, der alleine
stehen könnte! Anderenfalls wird im Icon der Text (none)
erscheinen.
{{- if gt (countrunes $fext) 1 -}}
...
{{- else -}}
(none)
{{- end -}}
Ist die Hürde der Dateiendung genommen, also es gibt irgendeine Zeichenkette,
muss deren Länge sinnvoll begrenzt werden. Unterlässt man das, sieht das Icon
“schlecht” aus, weil der Text über das Etikett hinausgeht. Außerhalb des
SVG-viewport
wird auch der Text beschnitten und nicht dargestellt. Maximal
passen vier Em (‘MMMM’) auf das Etikett. In der Regel können jedoch bis zu
fünf Zeichen dargestellt werden. Auf diese 5 Zeichen ist die Beschränkung
ausgelegt. Ist die Zeichenkette kurz genug, wird die Dateiendung
in voller Länge, aber ohne ‘.’ auf das ‘Etikett’ gebracht.
Ist die Zeichenkette länger, wird ebenfalls der Punkt rausgeworfen, aber nur
die ersten 4 Zeichen der Dateiendung übernommen. Der abgeschnittene Rest wird
durch ein ‘Ellipsis’ dargestellt.
{{- if le (countrunes $fext) 6 -}}
{{- delimit (first 1 (findRE "[^(.)].{0,4}" $fext)) " " -}}
{{- else -}}
{{- delimit (first 1 (findRE "[^(.)].{0,3}" $fext)) " " -}}
… <!-- ellipsis -->
{{- end -}}
Die Definition des Textes und des SVG endet regulär mit
</text>
</svg>
Auf diese Art bekommen wir eine blaue Diskette mit weißem Etikett. Die ‘Beschriftung’ stellt sich automatisch auf die angebotene Download-Datei ein. Es entfällt jeglicher Aufwand ein bestimmtes Icon für eine bestimmte Dateiendung zu erzeugen (z. B. png-Bilddatei), per Script zuzuordnen und zu pflegen.
Das erzeugte Download-Icon wird überall und unabhängig vom Browser gleichmässig dargestellt.
Versuche eine Bilddatei mit leerem Etikett zu nehmen und die Dateiendung per css darüber zu legen sind gescheitert. Der alte Ansatz mit einer Bilddatei für jede bekannte Dateiendung ist wegen des Aufwandes inakzeptabel.
Stand: 25.Oktober 2019