Adiciona extensão Twig com ícones SVG de plataformas acadêmicas

Cria AcademicIconsExtension com a função site_tools_academic_icon(name),
que retorna o SVG inline dos ícones Lattes (CNPq #005195), ORCID e
MathSciNet como Markup seguro, dispensando |raw nos templates.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-17 08:52:02 -03:00
parent 27134fce19
commit fc1f4537e1
3 changed files with 126 additions and 0 deletions

View File

@@ -7,6 +7,7 @@ Módulo Drupal com ferramentas utilitárias reutilizáveis para outros módulos
- **Menu de configuração "Local Modules"**: Fornece uma seção centralizada em `/admin/config/local-modules` para configurações de módulos desenvolvidos internamente.
- **Bloco Share Links**: Bloco de compartilhamento em redes sociais extensível via hooks.
- **Condição de visibilidade "Usuário da página é o usuário logado"**: Restringe a exibição de qualquer bloco à situação em que o usuário autenticado é o mesmo da rota `/user/{id}`.
- **Extensão Twig `site_tools_academic_icon`**: Função Twig para renderizar ícones SVG de plataformas acadêmicas (Lattes, ORCID, MathSciNet).
## Sub-módulos
@@ -117,6 +118,36 @@ O plugin `PageUserIsCurrentUser` adiciona uma condição de visibilidade reutili
Quando ativada, o bloco só é exibido se o usuário autenticado tiver o mesmo ID que o parâmetro `{id}` da rota `/user/{id}`. A opção **"Negar a condição"** inverte o comportamento (exibe para todos exceto o dono).
## Extensão Twig: ícones de plataformas acadêmicas
A função `site_tools_academic_icon(name)` retorna o SVG inline do ícone solicitado como marcação segura (sem necessidade de `|raw`).
### Ícones disponíveis
| Nome | Plataforma | Cor |
|------|------------|-----|
| `lattes` | Plataforma Lattes (CNPq) | `#005195` |
| `orcid` | ORCID | `#a6ce39` |
| `mathscinet` | MathSciNet (AMS) | `#0f4f96` |
### Uso em templates Twig
```twig
{{ site_tools_academic_icon('lattes') }}
{{ site_tools_academic_icon('orcid') }}
{{ site_tools_academic_icon('mathscinet') }}
```
O SVG já inclui `aria-hidden="true"` e `focusable="false"`. Para acessibilidade, envolva o ícone em um `<a>` com `aria-label`:
```twig
<a href="https://lattes.cnpq.br/{{ lattes_id }}"
target="_blank" rel="noopener noreferrer"
aria-label="{{ 'Currículo Lattes'|t }}">
{{ site_tools_academic_icon('lattes') }}
</a>
```
## Sub-módulo: site_tools_msc_2020
Widget de campo (`FieldWidget`) para seleção hierárquica de termos do vocabulário **MSC 2020** (Mathematics Subject Classification), com até 3 níveis em cascata via AJAX.

5
site_tools.services.yml Normal file
View File

@@ -0,0 +1,5 @@
services:
site_tools.twig_extension.academic_icons:
class: Drupal\site_tools\TwigExtension\AcademicIconsExtension
tags:
- { name: twig.extension }

View File

@@ -0,0 +1,90 @@
<?php
namespace Drupal\site_tools\TwigExtension;
use Drupal\Component\Render\MarkupInterface;
use Drupal\Core\Render\Markup;
use Twig\Extension\AbstractExtension;
use Twig\TwigFunction;
/**
* Extensão Twig que fornece ícones SVG de plataformas acadêmicas.
*
* Uso em templates:
* @code
* {{ site_tools_academic_icon('lattes') }}
* {{ site_tools_academic_icon('orcid') }}
* {{ site_tools_academic_icon('mathscinet') }}
* @endcode
*
* O retorno é Markup (já escapado), portanto não precisa de |raw.
*/
class AcademicIconsExtension extends AbstractExtension {
/**
* {@inheritdoc}
*/
public function getFunctions(): array {
return [
new TwigFunction('site_tools_academic_icon', $this->renderIcon(...), [
'is_safe' => ['html'],
]),
];
}
/**
* Retorna o SVG do ícone solicitado como Markup seguro.
*
* @param string $name
* Nome do ícone: 'lattes', 'orcid' ou 'mathscinet'.
*
* @return \Drupal\Component\Render\MarkupInterface
* Marcação SVG pronta para renderização.
*/
public function renderIcon(string $name): MarkupInterface {
return Markup::create(match ($name) {
'lattes' => $this->iconLattes(),
'orcid' => $this->iconOrcid(),
'mathscinet' => $this->iconMathSciNet(),
default => '',
});
}
/**
* Ícone da Plataforma Lattes (CNPq).
*
* Cor oficial CNPq: #005195.
*/
protected function iconLattes(): string {
return <<<'SVG'
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" aria-hidden="true" focusable="false">
<path fill="#005195" d="M 8.509,26.594 C 5.776,20.994 4.15,17.612 4.15,17.528 c 0,-0.137 0.167,-0.118 1.809,0.204 2.888,0.567 4.431,0.727 7.003,0.728 3.403,10e-4 6.174,-0.538 8.327,-1.621 1.139,-0.573 1.824,-1.081 2.385,-1.769 0.691,-0.848 0.913,-1.432 0.921,-2.415 0.007,-0.935 -0.119,-1.428 -0.66,-2.572 C 23.721,9.631 23.533,9.112 23.515,8.93 23.487,8.637 23.511,8.595 23.727,8.57 c 0.472,-0.056 2.802,2.206 3.66,3.553 1.479,2.323 1.599,4.836 0.347,7.266 -0.769,1.493 -1.619,2.526 -3.042,3.7 -2.365,1.95 -5.114,3.308 -8.91,4.402 -2.039,0.588 -5.336,1.301 -6.015,1.301 -0.144,0 -0.414,-0.472 -1.256,-2.199 z M 9.27,17.563 C 6.615,17.219 4.387,16.92 4.318,16.898 4.2,16.86 3.778,15.452 3.54,14.306 3.48,14.016 3.392,13.248 3.344,12.598 3.13,9.698 3.761,7.693 5.452,5.89 8.315,2.84 14.445,2.469 21.361,4.927 22.575,5.359 23.057,5.659 22.834,5.846 22.669,5.984 21.551,5.982 19.619,5.84 16.599,5.618 14.3,6.038 13.115,7.03 c -1.804,1.51 -1.529,4.82 0.798,9.595 0.252,0.517 0.506,1.023 0.564,1.126 0.135,0.237 0.037,0.457 -0.198,0.446 -0.1,-0.005 -2.354,-0.29 -5.009,-0.634 z m 8.907,-2.598 c -2.119,-0.381 -4.024,-1.695 -4.639,-3.198 -0.295,-0.722 -0.281,-1.664 0.034,-2.228 0.285,-0.51 1.021,-1.1 1.68,-1.347 1.097,-0.411 3.018,-0.247 4.418,0.378 1.329,0.593 2.507,1.636 2.945,2.606 0.562,1.245 0.094,2.634 -1.11,3.297 -0.798,0.439 -2.349,0.668 -3.329,0.492 z"/>
</svg>
SVG;
}
/**
* Ícone oficial ORCID.
*/
protected function iconOrcid(): string {
return <<<'SVG'
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" aria-hidden="true" focusable="false">
<circle cx="128" cy="128" r="128" fill="#a6ce39"/>
<path fill="#fff" d="M86.3 175.6V86h22.3v89.6H86.3zm11.1-101.8c-7.1 0-11.7-4.8-11.7-10.8 0-6.1 4.7-10.8 12-10.8s11.7 4.7 11.7 10.8c0 6-4.6 10.8-12 10.8zm32.9 101.8V86h21.1v12.6h.3c2.9-5.5 10.1-12.9 22.1-12.9 23.6 0 28 15.5 28 35.7v54.2h-22.2v-48c0-11.5-.2-26.2-16-26.2-16 0-18.4 12.5-18.4 25.4v48.8h-15z"/>
</svg>
SVG;
}
/**
* Ícone MathSciNet (AMS).
*/
protected function iconMathSciNet(): string {
return <<<'SVG'
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
<rect width="24" height="24" rx="4" fill="#0f4f96"/>
<text x="12" y="17" text-anchor="middle" font-family="serif" font-size="14" font-weight="bold" fill="#fff">Σ</text>
</svg>
SVG;
}
}