Icons
This extension ships the icons the academic extensions share: the actions of a control, the states a control shows, and the glyphs in front of a piece of information such as a phone number or an address. An icon that means the same in several extensions exists once, here, so a site package that replaces it replaces it everywhere.
They are frontend icons. They are registered in the frontend icon registry of
this extension, in its Configuration/, and the
templates of the academic extensions render them with the view helper
ab:, see Frontend icons. The
backend does not show them, and the icon registry of TYPO3 does not know them.
Every icon is a Font Awesome Free icon of the solid style, drawn in
current and registered with
\FGTCLB\
(see Icons that follow the text colour).
It therefore takes the colour of the text around it, and it sizes itself by
the font size: every file carries width="1em" and height="1em".
Identifiers and files
The identifiers follow tx-<extension key without underscores>-<group>-<name>,
the files Resources/. This extension
uses three groups:
action, something a control does,state, a state a control shows,info, the glyph in front of a piece of information.
The other academic extensions name their icons the same way. The group decides
the registry: an action, state or info icon is a frontend icon,
registered in Configuration/, and a record,
plugin or doktype icon, the icon of a record type, a content element or a
page type, is a backend icon, registered in Configuration/Icons.php.
The icons of category types and category groups are the exception: their
identifiers are derived by EXT: from the
Configuration/ that declares them, and they reach
both registries. Their files live in the directories category-
and category-, or are files of this set.
The tables below give the file relative to
EXT: and the name of the icon in
Font Awesome.
Actions
| Identifier | Meaning | File | Font Awesome |
|---|---|---|---|
tx- | Add an item | action/ | plus |
tx- | Go back | action/ | arrow- |
tx- | Clear a field | action/ | eraser |
tx- | Close or dismiss | action/ | xmark |
tx- | Collapse a section | action/ | minus |
tx- | Delete an item | action/ | trash- |
tx- | Drag-and-drop handle | action/ | grip- |
tx- | Edit | action/ | pen |
tx- | Expand a section | action/ | plus |
tx- | Show or hide a help text | action/ | circle- |
tx- | Move one position down | action/ | arrow- |
tx- | Move one position up | action/ | arrow- |
tx- | Save | action/ | floppy- |
tx- | Undo or reset | action/ | rotate- |
tx- | Upload or replace an image | action/ | camera |
tx- | Show a preview | action/ | eye |
tx- | Close the preview | action/ | eye- |
States
| Identifier | Meaning | File | Font Awesome |
|---|---|---|---|
tx- | Item is hidden (switch off) | state/ | toggle- |
tx- | Item is visible (switch on) | state/ | toggle- |
Information
| Identifier | Meaning | File | Font Awesome |
|---|---|---|---|
tx- | Date | info/ | calendar- |
tx- | Company or institution | info/ | building |
tx- | Contract | info/ | file- |
tx- | Degree | info/ | graduation- |
tx- | Department or faculty | info/ | building- |
tx- | info/ | envelope | |
tx- | Employment or job | info/ | briefcase |
tx- | Additional information | info/ | circle- |
tx- | International | info/ | earth- |
tx- | Link | info/ | link |
tx- | Location or address | info/ | location- |
tx- | Partnership or cooperation | info/ | handshake |
tx- | Person, a contact | info/ | user |
tx- | Phone | info/ | phone |
tx- | Recommendation | info/ | star |
tx- | Role | info/ | user- |
tx- | Room | info/ | door- |
tx- | Sector or industry | info/ | industry |
tx- | Time, office hours | info/ | clock |
expand and add are the same drawing in two files, so a site package can
replace one without the other.
Five of the nineteen information identifiers are rendered by a template of
the academic extensions: -info-, -info-, -info-,
-info- and -info-. The other fourteen stay registered on purpose,
so a site package can render and replace them like the others. The job views
render identifiers of academic_jobs that draw the same files, and
several files are also the drawings of record and category type icons, which
other academic extensions register under identifiers of their own. A
replacement of one of the fourteen therefore changes neither the job views nor
those record and category type icons.
Rendering an icon
In a Fluid template of the frontend, with the view helper of this extension:
<html xmlns:ab="http://typo3.org/ns/FGTCLB/AcademicBase/ViewHelpers"
data-namespace-typo3-fluid="true">
<ab:icon identifier="tx-academicbase-info-phone" alternativeMarkupIdentifier="inline" />
</html>
The markup is the inlined file with or without
alternative, because the provider inlines both
markups. The argument keeps the icon inlined where a site package replaces it
with the core
\TYPO3\,
which inlines the file only when it is asked to.
The rendered icon carries the CSS class icon-<identifier>, for example
icon-, and the attribute data-. A
stylesheet can address it through either.
<core: does not render
these icons: it reads the icon registry of TYPO3 and shows its not-found icon
for them.
Replacing an icon in a site package
Register the same identifier again in
Configuration/ of the site package. The later
registration wins, and every template of every academic extension that renders
the identifier shows the replacement:
return [
'tx-academicbase-info-phone' => [
'provider' => \FGTCLB\AcademicBase\Imaging\IconProvider\CurrentColorSvgIconProvider::class,
'source' => 'EXT:my_sitepackage/Resources/Public/Icons/phone.svg',
],
];
- The site package has to load after this extension: it requires
fgtclb/academic-base
, or an academic extension, which requires
it, in its
composer., and in classic mode names it underjson dependsin itsext_as well. The files are read in the loading order of the packages, and without the dependency the site package may be read first and lose.emconf. php - The entry replaces the whole registration, provider and source alike.
- Keep the replacement drawable for inlining if it stays with
Current: aColor Svg Icon Provider view,Box current, noColor idand no<style>, see What the SVG file must look like. - Flush the system caches afterwards.
An entry in Configuration/Icons.php changes nothing in the frontend,
the frontend registry does not read that file. The record, content element and
page type icons of the academic extensions are the other way round: they are
backend icons, and a site package replaces them in its
Configuration/Icons.php.
Icons in frontend JavaScript
The backend JavaScript icon API of TYPO3 cannot be used on a frontend page: it asks a backend route that answers a logged-in backend user only, and it serves the icon registry of TYPO3. Frontend JavaScript therefore takes the markup of an icon of the frontend icon registry from the server.
Note
The contracts this section documents are public API of this extension, as the extension points page lists them. They change only in a major release, with a Breaking changelog entry. The PHP classes behind them are not public API.
Where the JavaScript stamps out a piece of markup anyway, a list item or a row
with its buttons, render the icon with ab: into a
<template>
element and clone it. Where it picks an icon by its identifier at runtime,
hand it the icons it may need as a JSON map:
<html xmlns:ab="http://typo3.org/ns/FGTCLB/AcademicBase/ViewHelpers"
data-namespace-typo3-fluid="true">
<ab:frontendIconMap identifiers="{0: 'tx-academicbase-action-add', 1: 'tx-academicbase-action-delete'}" />
This renders a JSON data block that the browser neither executes nor checks against the Content Security Policy:
<script type="application/json" data-academic-icons data-academic-icons-size="small">{"tx-academicbase-action-add":"\u003Cspan class=\u0022t3js-icon icon icon-size-small ...\u0022 ...\u003E...\u003C/span\u003E","tx-academicbase-action-delete":"..."}</script>
Each value is the markup <ab: renders, so the replacement of an icon
in a site package arrives in the JavaScript as it does in a template. The JSON
escapes <, >, & and both quotes as unicode escapes, so no markup can end
the element, and
JSON. returns the plain markup.
Arguments:
identifiers(array, required)- The identifiers to render. One that is not served is left out of the map, see below.
size(string, defaultsmall)default,small,medium,largeormega. It sets theicon-class of the markup. The icons of the academic extensions size themselves by the font size.size-* endpoint(bool, defaultfalse)- Adds
data-andacademic- icons- url data-to the element: the icon endpoint of the current site language and the version token of the served icons. Outside a site both are left out.academic- icons- version
The icon endpoint
Where the JavaScript learns an identifier only after the page was rendered, from data it loads or from a choice of the visitor, it asks the icon endpoint of the site:
GET https://example.com/_academic/icons.json?i=tx-academicbase-action-add,tx-academicbase-info-phone&s=small&v=<token>
The answer is a JSON object in the same shape as the JSON map, for the
identifiers that are served, in the order asked for. The endpoint is available
below the base of every site and site language, for example
https://. Its path, its parameters, its
answer and its caching are public API like the rest of this section.
i(required)- Up to 32 icon identifiers, separated by commas.
s(optional, defaultsmall)default,small,medium,largeormega.v(optional)- The version token of the served icons, as
data-of the JSON map carries it. With the current token the answer may be cached for a year (academic- icons- version Cache-), otherwise for five minutes. The answer carries anControl: public, max- age=31536000, immutable ETagand answers a matchingIf-withNone- Match 304 Not Modified. TheETagonly helps the five-minute answers, an immutable one is never revalidated.
A malformed identifier, more than 32 of them or an unknown size are answered
with 400 Bad Request, any method other than GET and HEAD with
405 Method Not Allowed. The endpoint answers before the frontend user
authentication: it never starts a session and never sets a cookie, so a proxy
or a CDN can cache it like a file. A site in maintenance mode answers it with
503, like every page.
The token covers what decides the markup of a served icon:
- the identifiers the frontend icon registry serves and their registrations, so a site package that replaces an icon changes it once the system caches are flushed,
- the modification time of each source file,
- the modification time of the class files of each provider and of the classes it extends, so a provider changed in place changes it as well,
- TYPO3's package dependent cache identifier: the TYPO3 version, the project
path and, in composer mode, the content of
composer..lock
A deployment that writes the files anew therefore changes the token, and the browsers fetch the icons once more. Not covered is other rendering code changed in place without any of these, the icon markup of TYPO3 or the SVG sanitiser library edited on the server. Touch the SVG files of the affected icons then.
Each web node computes the token from its own file times and project path, so nodes that do not share one build compute different tokens, and a page rendered on one node gets the five-minute answer from another.
Important
Web server requirement. The path ends in .json. A web server or CDN
rule that serves *. as static files, in nginx for example a
location ~* . with try_,
answers the endpoint with a 404 before TYPO3 sees it. Exclude
_academic/ from such a rule, the way sitemap. is usually
excluded.
The icon factory
Both are read by the JavaScript module
@fgtclb/, which this extension publishes in
its import map. The module and its exports are public API like the rest of
this section.
A module asks it for an icon by its identifier. The factory answers from the
JSON maps of the page and asks the endpoint only for what the page does not
carry, collecting the icons asked for at the same time into one request. The
request names them sorted by identifier, so the same icons always make the
same URL and a browser or a proxy caches their answer once:
<div class="my-plugin" data-my-plugin>
<ab:frontendIconMap identifiers="{0: 'tx-academicbase-action-add'}" endpoint="1" />
</div>
<f:asset.module identifier="@my-vendor/my-sitepackage/frontend/my-plugin.js" />
import { IconFactory, Sizes, endpointFrom } from '@fgtclb/academic-base/frontend/icons.js';
const root = document.querySelector('[data-my-plugin]');
const icons = new IconFactory(endpointFrom(root));
// From the JSON map of the page, without a request.
button.append(await icons.getIconElement('tx-academicbase-action-add'));
// From the endpoint, in one request for both.
const [edit, remove] = await Promise.all([
icons.getIcon('tx-academicbase-action-edit', Sizes.medium),
icons.getIcon('tx-academicbase-action-delete', Sizes.medium),
]);
The extension or site package that ships the module has to name
academic_ in the dependencies of its import map. A page only carries the
import map entries of the packages its modules declare:
return [
'dependencies' => ['core', 'academic_base'],
'imports' => [
'@my-vendor/my-sitepackage/frontend/' => 'EXT:my_sitepackage/Resources/Public/JavaScript/frontend/',
],
];
get answers the markup, get a new element on every call,
and prefetch asks for several icons ahead of time. An identifier that is
not served, or that is not an icon identifier at all, rejects the promise. A
malformed one is never sent, so it cannot fail the icons asked for with it.
The factory reads every JSON map of the document, not only those inside the
element it was given, and the first map that carries an icon wins. An icon the
endpoint leaves out stays rejected for the page, unless a JSON map that
reaches the page later carries it.
Each icon is asked for once per page, without cookies. A request that fails or
gets no answer within ten seconds rejects its icons, and the next call asks
again. The browser keeps the answer of the endpoint as long as the token does
not change.
Which icons are served
The JSON map and the endpoint serve the same icons. The icons of the frontend
icon registry, and no other: what the
Configuration/ of an extension or a site package
registers, what a listener of CollectFrontendIconsEvent contributes, and
the icons of category types and category groups. The icon registry of TYPO3 is
never read, so a core icon or the backend icon of a record type is not served,
even when a template asks for its identifier. A site package hands an icon of
its own to its JavaScript by registering it in its
Configuration/, see
Frontend icons.
Of the frontend icons, three kinds are left out of the answer rather than answered with the placeholder of an unknown icon:
- the placeholder
default-itself, and an identifier the frontend registry does not know,not- found - an icon whose provider does not inline an SVG file: a bitmap icon, a
sprite icon or a font icon. Served are the icons of
Currentand of the coreColor Svg Icon Provider \TYPO3\,CMS\ Core\ Imaging\ Icon Provider\ Svg Icon Provider - an identifier that is longer than 100 characters, holds anything but
lowercase letters, digits,
_,.and-, or starts with.or-.
The markup is what the provider of the icon renders, sanitised as far as that
provider sanitises.
Current sanitises on TYPO3 v13
and v14, the inline markup of the core
Svg is sanitised on
TYPO3 v14 only. That is the same markup, with the same exposure, as the icon
rendered inline by a template.
Third-party icons
The SVG icons below Resources/, except
Extension., are Font Awesome Free
icons by Fonticons, Inc., licensed under the Creative Commons Attribution 4.0
International license. The
notice Resources/ lists every file
with its Font Awesome name and the changes made to it.
The files are taken from version 7.3.1. They are modified: the fill colour
moved to the root element, width and height were added, and each file is
named after its purpose. Each file keeps Font Awesome's attribution comment,
which the icon provider removes from the rendered markup together with every
other comment. Extension. is the icon of the extension itself and is
not part of the set.