Recentemente comecei a federar as coisas do Computaria no dev.to. E percebi sabe o quê? Que não tinha menção à minha conta do dev.to no footer. Tenho diversas outras redes sociais, mas não essa conta específica.
Então vamos adicionar?
Antes
Originalmente eu adicionava na mão todos os detalhes do footer
. O formato original era adicionar um elemento na lista:
<div class="footer-col footer-col-2">
<ul class="social-media-list">
{% if site.gitlab_username %}
<li>
{% include icon-gitlab.html username=site.gitlab_username %}
</li>
{% endif %}
<!-- outros elementos -->
</ul>
</div>
É uma lista uniforme seguindo sempre a mesma exata lógica:
- se eu tiver um user name
- adiciona um
<li>
cujo conteúdo é umicon-<media>.html
passando como argumentousername=<usuário checado antes>
E qual o formato geral do icon-<media>.html
? Por exemplo, o icon-gitlab.html
? (Exibido aqui pretty-printed)
<a href="https://gitlab.com/{{ include.username }}">
<span class="icon icon--gitlab">{% include icon-gitlab.svg %}</span>
<span class="username">{{ include.username }}</span>
</a>
Basicamente um link <a>
com href usando o username
passado como parâmetro. O conteúdo é um <span>
com classes icon
e icon--<media>
, e o conteúdo desse <span>
é um SVG incluído via Liquid: {% include icon-<media>.svg %}
.
E depois tem um span
com o username
com a classe username
.
Então, manter isso é bem trabalhoso... gostaria de um jeito que não precisar fazer tudo isso na mão.
O que é comum
Basicamente, a única coisa que realmente é única para cada elemento é o SVG de cada rede. De resto, poderíamos ter, em termos de Liquid:
<a href="{{ include.media_base_url}}/{{ include.username }}">
<span class="icon icon--{{include.media_name}}">{% include icon-{{include.media_name}}.svg %}</span>
<span class="username">{{ include.username }}</span>
</a>
Testando o Liquid
Ok, vamos tentar renderizar o link do gitlab. Primeiramente, criar o ícone template para incluir os links. Vou abstrair no _includes/social/icon.html
.
Vamos testar? Vou colocar dentro do <ul>
com a classe adequada para efeitos de exibição, para pegar as classes corretas. Vou também por em primeiro lugar o ícone original usado do gitlab e depois o ícone comum:
<ul class="social-media-list">
<li>{% include icon-gitlab.html
username=site.gitlab_username %}</li>
<li>{% include social/icon.html
username=site.gitlab_username
media_base_url="https://gitlab.com/"
media_name="gitlab" %}</li>
</ul>
Bem, foi sucesso, os dois ícones ficaram iguais, a única diferença foi uma barra a mais na URL dentro do href. Mas isso não é crítico e não interfere nada por hora.
Refatorando: datafiles
Para evitar ficar dando a manutenção manual em cada item individual, resolvi usar uma espécie de banco de dados de arquivo. Isso permite que eu consiga trabalhar sem me preocupar em montar manualmente cada elemento. E o Jekyll oferece já uma solução: datafiles.
Vamos criar um desses datafiles? _data/social_media.yaml
.
Primeiro, só para ver se de fato vai ter alguma iteração:
{% for social_media in site.data.social_media %}
oi oi oi
{% endfor %}
oi oi oi
oi oi oi
oi oi oi
oi oi oi
oi oi oi
oi oi oi
oi oi oi
Muito bom, de fato iterou. Agora, vamos listar os atributos? Por em um <li>
sem pretenção, separado por vírgulas. Pelo experimento anterior eu preciso de 3 atributos:
media_name
username
media_base_url
Vamos ver como fica?
<ul>
{% for social_media in site.data.social_media %}
<li>
{{social_media.media_name}}, {{social_media.username}}, {{social_media.media_base_url}}
</li>
{% endfor %}
</ul>
Os dados:
- media_name: "gitlab"
username: site.gitlab_username
media_base_url: "https://gitlab.com/"
- media_name: "github"
username: site.github_username
media_base_url: "https://github.com/"
Renderizou assim (eu fiz algumas alterações nos dados depois):
- gitlab, site.gitlab_username, https://gitlab.com/
- github, site.github_username, https://github.com/
Hmmm, eu queria ter acesso a dados do _config.yml
onde já tenho o gitlab_username
e outras coisas, e isso não deu certo. Eu queria poder cadastrar isso como referências, não literais. Mas como eu consigo testar se isso funciona mesmo?
Primeiro teste, botar duas vezes a expansão Liquid, algo como {{ {{ "site.gitlab_username" }} }}
?
Nah, não funcionou como eu esperava...
Hmmm, procurando um pouco mais sobre Liquid achei essas outras documentações:
E no Shopify Liquid achei uma referência ao operador []
na expansão de valores. Então, vamos testar? Pela doc, {{ site.gitlab_username }}
deveria renderizar igual a {{ site["gitlab_username"] }}
. Vamos testar?
<ul>
<li>{{ site.gitlab_username }}</li>
<li>{{ site["gitlab_username"] }}</li>
</ul>
Funcionou!! Vamos refazer o experimento de como renderizar? Ajustando para usar o []
:
<ul>
{% for social_media in site.data.social_media %}
<li>
{{social_media.media_name}}, {{ site[social_media.username]}}, {{social_media.media_base_url}}
</li>
{% endfor %}
</ul>
Os dados:
- media_name: "github"
username: github_username
media_base_url: "https://github.com/"
- media_name: "gitlab"
username: gitlab_username
media_base_url: "https://gitlab.com/"
Renderizou assim (eu fiz algumas alterações nos dados depois):
- gitlab, jefferson.quesado, https://gitlab.com/
- github, jeffque, https://github.com/
Massa!
Alterando o footer
Vamos alterar o footer. No lugar de usar literalmente cada verificação, vou simplesmente usar o datafile:
<ul class="social-media-list">
{% for social_media in site.data.social_media %}
<li>{% include social/icon.html
username=site[social_media.username]
media_base_url=social_media.media_base_url
media_name=social_media.media_name %}</li>
{% endfor %}
</ul>
E...
Ok, ok... e se no lugar de usar diretamente o site[social_media.username]
eu atribuir a uma variável?
<ul class="social-media-list">
{% for social_media in site.data.social_media -%}
{%- assign username = site[social_media.username] -%}
<li>{%- include social/icon.html
username=username
media_base_url=social_media.media_base_url
media_name=social_media.media_name -%}</li>
{% endfor %}
</ul>
Para temporariamente esses dados:
- media_name: "gitlab"
username: gitlab_username
media_base_url: "https://gitlab.com/"
- media_name: "github"
username: github_username
media_base_url: "https://github.com/"
Renderizou assim
Muito bem, hora de expandir
Um parêntese antes de expandir, controlando o espaçamento
Na real, a renderização foi (com exceção do SVG) assim:
<ul class="social-media-list">
<li><a href="https://gitlab.com//jefferson.quesado"><span class="icon icon--gitlab">{% include icon-gitlab.svg %}
</span><span class="username">jefferson.quesado</span></a></li>
<li><a href="https://github.com//jeffque"><span class="icon icon--github">{% include icon-github.svg %}
</span><span class="username">jeffque</span></a></li>
</ul>
E isso tinha muito espaço em branco. Vou colocar aqui o diff da versão que renderizou com esses espaços para o da versão que gerou sem o excesso de espaços:
<ul class="social-media-list">
- {% for social_media in site.data.social_media %}
- {% assign username = site[social_media.username] %}
- <li>{% include social/icon.html
+ {% for social_media in site.data.social_media -%}
+ {%- assign username = site[social_media.username] -%}
+ <li>{%- include social/icon.html
username=username
media_base_url=social_media.media_base_url
- media_name=social_media.media_name %}</li>
+ media_name=social_media.media_name -%}</li>
{% endfor %}
</ul>
Notou a diferença? Foram só os tracinhos nos filtros. Isso permitiu fazer o controle de espaços. Colocar o traço no começo do for
causou uma ausência muito grande de espaços que me incomodou, o <li>
encostado no <ul>
.
A exceção: StackOverflow
Bem, o StackOverflow segue um outro padrão que não uma URL seguido do nome do usuário. O padrão é:
https://pt.stackoverflow.com/users/<userid>/<username>
Ou seja, agora tenho duas variáveis, não apenas uma. Inclusive o mais importante é o ID para mostrar o usuário correto. Inclusive, ao tentar acessar https://pt.stackoverflow.com/users/64969/, você é direcionado para https://pt.stackoverflow.com/users/64969/jefferson-quesado.
Vamos definir um novo campo no yaml: media_url_literal
. Posto isto, não se faz necessário mais a construção da URL. Vamos passar isso adiante e deixar com o icon
para lidar com qual usar.
No href
, vou por para renderizar o include.media_url_literal
se ele existir, caso contrário vou para o método de construção de URL em cima do username
que já tinha antes:
<a href="{%- if include.media_url_literal -%}{{include.media_url_literal}}{%- else -%}{{ include.media_base_url }}/{{ include.username }}{% endif %}">
<span class="icon icon--{{include.media_name}}">{% include icon-{{include.media_name}}.svg %}</span>
<span class="username">{{ include.username }}</span>
</a>
E na chamada eu simplesmente passo o novo atributo:
{%- include social/icon.html
username=username
media_base_url=social_media.media_base_url
media_url_literal=social_media.media_url_literal
media_name=social_media.media_name -%}
Username literal
Peguei outro caso excepcional: quando preciso lidar com nome literal, no lugar de nome via referência. Para lidar com isso, aproveitei que já tinha uma atribuição sendo feita à variável username
e coloquei um trecho condicional.
Saí disso:
{%- assign username = site[social_media.username] -%}
Para isso:
{%- if social_media.username_literal -%}
{%- assign username = social_media.username_literal -%}
{%- else -%}
{%- assign username = site[social_media.username] -%}
{% endif %}
E assim consegui renderizar do jeito que eu queria.
Mas, sinceramente? Isso me parece um tanto quanto... cumbersome... muitos comandos Liquid. Será que eu posso usar a tag liquid
?
Pelo que eu li, seria assim:
{%- liquid
if social_media.username_literal
assign username = social_media.username_literal
else
assign username = site[social_media.username]
endif
-%}
E a resposta é...
... não:
Unknown tag 'liquid'
Ok, ao menos tentei. Talvez atualizar o Liquid usado no computaria no futuro?
Escondendo o que não quero mostrar
Ok, não tenho gostado do ramo que o Twitter tomou, inclusive em maior parte saí de lá. Mas... a rede social tá lá, né? Já que estou catalogando minhas redes sociais, vou ao menos cadastrar o Twitter no meu datafile. Mas para isso preciso também esconder ele, já que ativamente não quero mais mostrar.
Tentei inicialmente usar no for
um filtro where
, o que não deu muito certo...
{% for social_media in social_media_shown | where: "show" %}
{% endfor %}
Não fez efeito algum. Então resolvi fazer o exemplo que estava vendo associado ao where
: colocar no assign
.
Tentei isso
{% assign social_media_shown = site.data.social_media | where: "show" %}
e com isso obtive
Liquid error (line 485): wrong number of arguments (given 2, expected 3)
Ué. Mas é bem dizer o exemplo do site! Mas, será que... Bem, o próprio Liquid admite que existem duas versões do Liquid, o Spotify Liquid e o Jekyll Liquid. Será que eu peguei o caso em que diferenciam?
Vamos ver a documentação do Jekyll Liquid em relação ao where
...
Select all the objects in an array where the key has the given value.
E o exemplo
{{ site.members | where:"graduation_year","2014" }}
É, peguei justamente o caso em que o Jekyll Liquid difere do padrão...
Mas olha que legal logo ali debaixo do where
, em where_exp
!
Select all the objects in an array where the expression is true.
Com os exemplos:
{{ site.members | where_exp:"item", "item.graduation_year < 2014" }}
Ou seja, o primeiro argumento se torna o alias do elemento dentro da expressão, e o segundo argumento é a expressão em si! Será que temos alguma expressão para pegar apenas quem tem show != false
?
{% assign social_media_shown = site.data.social_media | where_exp: "social_media", "social_media.show != false" %}
{%- for social_media in social_media_shown -%}
- {{social_media.media_name}}
{% endfor %}
- gitlab
- github
- bsky
- stackoverflow
- devto
Com o resultado esperado.
Limpeza final
Basicamente os icon-<media>.html
perderam sentido de ser. O icon-gitlab.html
vai ser mantido por conta do exemplo usado nesta publicação e também por conta das coisas no sobre.
O icon-stackoverflow.html
também é usado na mesma página. Então vou manter esses dois. Já os outros não tem necessidade. Vou remover e deixar o _includes
limpo.
Top comments (0)