recursero-jekyll-theme 0.1.3 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +69 -18
  3. data/_config.yml +77 -0
  4. data/_data/assets.json +6 -0
  5. data/_data/en.yml +61 -15
  6. data/_data/es.yml +64 -15
  7. data/_data/forms/contacto.yml +2 -2
  8. data/_data/layouts/about.yml +34 -17
  9. data/_data/layouts/menu.yml +73 -0
  10. data/_includes/contact.html +8 -5
  11. data/_includes/floating_alert.html +6 -0
  12. data/_includes/item.html +38 -0
  13. data/_includes/menu.html +23 -0
  14. data/_includes/onboarding.html +37 -0
  15. data/_includes/pack.html +1 -0
  16. data/_includes/password.html +1 -0
  17. data/_includes/picture.html +23 -0
  18. data/_includes/preload_font.html +1 -0
  19. data/_includes/search.html +4 -3
  20. data/_includes/share.html +3 -2
  21. data/_includes/submit.html +5 -1
  22. data/_layouts/about.html +1 -1
  23. data/_layouts/default.html +34 -2
  24. data/_layouts/page.html +1 -1
  25. data/_layouts/place.html +1 -1
  26. data/_layouts/post.html +2 -2
  27. data/_sass/accessibility.scss +48 -7
  28. data/_sass/editor.scss +17 -0
  29. data/_sass/embed.scss +8 -0
  30. data/_sass/floating_alert.scss +48 -0
  31. data/_sass/fonts.scss +0 -0
  32. data/_sass/helpers.scss +327 -31
  33. data/_sass/menu.scss +36 -0
  34. data/_sass/snap.scss +60 -0
  35. data/_sass/toggler.scss +34 -11
  36. data/assets/css/styles.scss +89 -7
  37. data/assets/data/manifest.js +29 -0
  38. data/assets/fonts/forkawesome-webfont.woff2 +0 -0
  39. data/assets/js/pack.3cf11284b767fdbbefa6.js +113 -0
  40. data/assets/js/pack.3cf11284b767fdbbefa6.js.map +1 -0
  41. data/assets/js/pack.4ced2556b94e5c09e5bc.js +113 -0
  42. data/assets/js/pack.4ced2556b94e5c09e5bc.js.map +1 -0
  43. data/assets/js/pack.c42a6f683b2c0c0fa404.js +90 -0
  44. data/assets/js/pack.c42a6f683b2c0c0fa404.js.map +1 -0
  45. data/assets/js/pack.d9a353affdca4644a9b2.js +113 -0
  46. data/assets/js/pack.d9a353affdca4644a9b2.js.map +1 -0
  47. data/assets/js/sw.3cf11284b767fdbbefa6.js +2 -0
  48. data/assets/js/sw.3cf11284b767fdbbefa6.js.map +1 -0
  49. data/assets/templates/alert.html +7 -0
  50. data/assets/templates/results.html +15 -7
  51. metadata +82 -45
  52. data/_includes/navbar.html +0 -53
  53. data/_sass/share.html +0 -12
  54. data/_sass/share_box.html +0 -16
  55. data/assets/js/pack.js +0 -90
  56. data/assets/js/pack.js.map +0 -1
@@ -0,0 +1,73 @@
1
+ ---
2
+ title:
3
+ type: 'string'
4
+ required: true
5
+ label:
6
+ en: ''
7
+ es: 'Nombre del ítem'
8
+ help:
9
+ en: ''
10
+ es: 'Tal como aparece en el menú'
11
+ post:
12
+ type: 'belongs_to'
13
+ label:
14
+ en: ''
15
+ es: 'Artículo'
16
+ help:
17
+ en: ''
18
+ es: 'Si el ítem lleva a un artículo fijo, asociarlo aquí'
19
+ item:
20
+ type: 'belongs_to'
21
+ inverse: items
22
+ filter:
23
+ layout: menu
24
+ label:
25
+ en: ''
26
+ es: 'Ítem anterior'
27
+ help:
28
+ en: ''
29
+ es: 'Si es un sub ítem, asociar el ítem superior aquí'
30
+ items:
31
+ type: 'has_many'
32
+ inverse: item
33
+ filter:
34
+ layout: menu
35
+ label:
36
+ en: ''
37
+ es: 'Sub ítemes'
38
+ help:
39
+ en: ''
40
+ es: 'Si el ítem tiene sub ítems, asociarlos aquí'
41
+ link:
42
+ type: 'string'
43
+ label:
44
+ en: ''
45
+ es: 'Vínculo'
46
+ help:
47
+ en: ''
48
+ es: 'Si el ítem lleva a una página o sección especial, asociarla aquí'
49
+ categories:
50
+ type: 'array'
51
+ label:
52
+ en: ''
53
+ es: 'Categorías'
54
+ help:
55
+ en: ''
56
+ es: 'Si el ítem lleva un sub menú de categorías, agregarlas aquí'
57
+ draft:
58
+ type: 'boolean'
59
+ label:
60
+ es: 'Borrador'
61
+ en: 'Draft'
62
+ help:
63
+ es: 'Este artículo aun no está listo para publicar'
64
+ en: "This post isn't ready to be published yet"
65
+ order:
66
+ type: 'order'
67
+ required: true
68
+ label:
69
+ es: 'Orden'
70
+ en: 'Order'
71
+ help:
72
+ es: 'La posición del artículo en la lista de artículos'
73
+ en: 'The post position in the posts list'
@@ -1,15 +1,18 @@
1
1
  {% comment %}
2
- Esta imagen obtiene una cookie desde la API de Sutty para autorizar el
3
- envío del formulario.
2
+ Esta imagen obtiene una cookie desde la API de Sutty para autorizar el
3
+ envío del formulario.
4
4
  {% endcomment %}
5
- <img class="d-none" src="https://api.sutty.nl/v1/sites/{{ site.hostname }}/contact/cookie.png" />
5
+ <img class="d-none invisible" src="https://api.sutty.nl/v1/sites/{{ site.hostname }}/contact/cookie.png" />
6
6
 
7
7
  {% comment %}
8
8
  El formulario se envía a la API. La definición del formulario se
9
9
  encuentra en _data/forms/contacto.yml
10
10
  {% endcomment %}
11
- <form action="https://api.sutty.nl/v1/sites/{{ site.hostname }}/contact/contacto"
12
- method="post">
11
+ <form
12
+ data-controller="contact"
13
+ data-delay="60"
14
+ action="https://api.sutty.nl/v1/sites/{{ site.hostname }}/contact/{{ include.name }}"
15
+ method="post">
13
16
  {%- for field in include.form -%}
14
17
  {% assign template = field[1].type | append: '.html' %}
15
18
  <div class="col{{ field[1].col | default: 12 | prepend: '-' }}">
@@ -0,0 +1,6 @@
1
+ <div
2
+ data-controller="floating-alert"
3
+ class="floating-alert floating-alert-bottom floating-alert-default"
4
+ role="status" aria-live="polite" aria-atomic="true">
5
+ <div data-target="toast.content" class="floating-alert-content white background-black-t4"></div>
6
+ </div>
@@ -0,0 +1,38 @@
1
+ {%- comment -%}
2
+ El ítem tiene un dropdown si tiene sub ítems o si tiene categorías.
3
+ {%- endcomment -%}
4
+ {%- assign dropdown = include.item.items | present -%}
5
+ {%- unless dropdown -%}
6
+ {%- assign dropdown = include.item.categories | present -%}
7
+ {%- endunless -%}
8
+
9
+ <div class="nav-item w-100 w-lg-auto {{ dropdown | value_if: 'dropdown d-flex flex-wrap' }}">
10
+ {%- comment -%}
11
+ La URL del item puede ser:
12
+ * El artículo vinculado
13
+ * El vínculo escrito manualmente
14
+ * La primera categoría de la lista
15
+ * La dirección propia (en el caso de categorías)
16
+ {%- endcomment -%}
17
+ <a
18
+ href="{{ include.item.post.url | default: include.item.link | default: include.item.categories[0].url | default: include.item.url }}"
19
+ class="nav-link flex-grow-1 flex-grow-lg-0">
20
+ {{ include.item.title }}
21
+ </a>
22
+
23
+ {%- if dropdown -%}
24
+ <button class="dropdown-toggle border-0 background-white w-5 w-lg-auto pl-lg-3"></button>
25
+ <div class="dropdown-menu w-100 w-lg-auto flex-grow-1 flex-grow-lg-0">
26
+ {% for item in include.item.items %}
27
+ {%- include_cached item.html item=item -%}
28
+ {% endfor %}
29
+
30
+ {%- comment -%}
31
+ Esto necesita `replace` en sutty-archives
32
+ {%- endcomment -%}
33
+ {%- for item in include.item.categories offset: 1 -%}
34
+ {%- include_cached item.html item=item -%}
35
+ {%- endfor -%}
36
+ </div>
37
+ {%- endif -%}
38
+ </div>
@@ -0,0 +1,23 @@
1
+ {%- comment -%}
2
+ Empezamos con los ítems que no dependen de otros e implementamos
3
+ recursivamente.
4
+ {%- endcomment -%}
5
+ {%- assign items = site.posts | where: 'layout', 'menu' | where: 'item', nil -%}
6
+
7
+ <nav class="navbar navbar-expand-lg navbar-light">
8
+ <button class="navbar-toggler"
9
+ type="button"
10
+ data-toggle="collapse"
11
+ data-target="#menu"
12
+ aria-label="{{ site.i18n.menu.title }}">
13
+ <span class="navbar-toggler-icon"></span>
14
+ </button>
15
+
16
+ <div class="collapse navbar-collapse" id="menu">
17
+ <div class="navbar-nav w-100 d-flex align-items-start justify-content-center">
18
+ {% for item in items %}
19
+ {%- include_cached item.html item=item -%}
20
+ {% endfor %}
21
+ </div>
22
+ </div>
23
+ </nav>
@@ -0,0 +1,37 @@
1
+ {% comment %}
2
+ La barra de notificaciones, donde le pedimos a les usuaries que vayan
3
+ haciendo varias cosas. Quizás debería llamarse onboarding.
4
+
5
+ Primero tenemos que poder salir del navegador interno de Facebook,
6
+ Instagram, Telegram, etc.
7
+ {% endcomment %}
8
+
9
+ <aside
10
+ data-sw="{{ jekyll.production | ternary: site.data.assets['sw.js'], 'sw.js' }}"
11
+ data-controller="onboarding"
12
+ class="w-100 background-primary"
13
+ role="status"
14
+ aria-live="polite"
15
+ aria-atomic="true">
16
+ <div data-onboarding-target="internalBrowser" hidden>
17
+ <div class="h-20vh d-flex align-items-center">
18
+ {% comment %}
19
+ Con esta URL le decimos a Android y posible iOS que queremos abrir
20
+ este link en un navegador externo.
21
+
22
+ https://stackoverflow.com/a/58342222
23
+ {% endcomment %}
24
+ <a href="intent:{{ site.url }}#Intent;end" class="btn btn-block btn-primary">
25
+ {{ site.i18n.onboarding.internal_browser }}
26
+ </a>
27
+ </div>
28
+ </div>
29
+
30
+ <div data-onboarding-target="browser" hidden>
31
+ <div class="h-20vh d-flex align-items-center">
32
+ <button data-action="onboarding#install" class="btn btn-block btn-primary">
33
+ {{ site.i18n.onboarding.browser }}
34
+ </button>
35
+ </div>
36
+ </div>
37
+ </aside>
@@ -0,0 +1 @@
1
+ <script defer src="{{ jekyll.production | ternary: site.data.assets['assets/js/pack.js'], 'assets/js/pack.js' }}"></script>
@@ -0,0 +1 @@
1
+ {% include input.html field=include.field form=include.form %}
@@ -0,0 +1,23 @@
1
+ {% comment %}
2
+ Imágenes responsive. Esto logra que solo se carguen las versiones de
3
+ las imágenes con el ancho máximo de la pantalla.
4
+
5
+ TODO: Las imágenes en md y superior nunca llegan al ancho máximo así
6
+ que tienen una resolución de más.
7
+ {% endcomment %}
8
+ {%- assign image = include.image.path | default: 'public/placeholder.png' %}
9
+ {%- assign height = include.height | default: site.i18n.post.height -%}
10
+ {%- assign width = include.width | default: '100' -%}
11
+
12
+ <picture>
13
+ {% for size in site.images.sizes %}
14
+ <source srcset="{{ image | thumbnail: size }}" media="(max-width: {{ size }}px)" />
15
+ {% endfor %}
16
+
17
+ <img
18
+ class="u-photo w-{{ width }} {{ include.cover | equals: false | value_unless: 'fit-cover' }} h-{{ height }} {{ include.extra }}"
19
+ loading="lazy"
20
+ itemprop="image"
21
+ src="{{ image | thumbnail: 1140 }}"
22
+ alt="{{ include.image.description | include.default_description }}" />
23
+ </picture>
@@ -0,0 +1 @@
1
+ <link rel="preload" as="font" type="font/woff2" crossorigin href="{{ include.font }}?{{ site.time | date: '%s' }}" />
@@ -1,15 +1,16 @@
1
1
  {%- comment -%}
2
2
  Encabezado con buscador
3
3
  {%- endcomment -%}
4
+ {%- assign param = include.param | default: 'search' -%}
4
5
  <section id="{{ site.i18n.search.id }}">
5
6
  <div class="jumbotron">
6
- <form method="get" class="search" action="{{ site.i18n.search.url }}" data-controller="search">
7
+ <form method="get" class="search" action="{{ site.i18n.search.url }}" data-controller="search" data-action="search#search">
7
8
  <div class="form-group">
8
- <label for="search" class="sr-only">{{ site.i18n.search.placeholder }}</label>
9
+ <label for="{{ param }}_q" class="sr-only">{{ site.i18n.search.placeholder }}</label>
9
10
  <input
10
11
  type="search"
11
12
  required
12
- id="q"
13
+ id="{{ param }}_q"
13
14
  name="q"
14
15
  placeholder="{{ site.i18n.search.placeholder }}"
15
16
  class="form-control form-control-lg m-0"
data/_includes/share.html CHANGED
@@ -5,6 +5,7 @@
5
5
  {% endunless %}
6
6
  {% assign title = include.title | default: '' | cgi_escape %}
7
7
  {% assign description = include.description | default: '' | cgi_escape %}
8
+ {% assign tags = include.tags | join: ',' | default: '' | cgi_escape %}
8
9
 
9
10
  <a
10
11
  {% if include.share.url == '%url' %}
@@ -12,10 +13,10 @@
12
13
  {% else %}
13
14
  target="_blank"
14
15
  {% endif %}
15
- rel="nofollow"
16
+ rel="noopener nofollow"
16
17
  title="{{ include.share.title }}"
17
18
  class="d-flex flex-column align-items-center p-3"
18
- href="{{ include.share.url | replace: '%url', url | replace: '%title', title | replace: '%description', description }}">
19
+ href="{{ include.share.url | replace: '%url', url | replace: '%title', title | replace: '%description', description | replace: '%tags', tags }}">
19
20
  <i class="fa fa-fw fa-2x fa-{{ include.share.icon }}"></i>
20
21
  <span>{{ include.share.title }}</span>
21
22
  </a>
@@ -1 +1,5 @@
1
- <input type="submit" class="btn btn-success" value="{{ include.field[1].label[site.locale] }}" />
1
+ <input
2
+ data-target="contact.submit"
3
+ type="submit"
4
+ class="btn btn-success"
5
+ value="{{ include.field[1].label[site.locale] }}" />
data/_layouts/about.html CHANGED
@@ -22,7 +22,7 @@ layout: default
22
22
 
23
23
  <p>
24
24
  <time class="dt-published" datetime="{{ page.date | date_to_xmlschema }}" itemprop="datePublished">
25
- {%- assign date_format = site.i18n.date | default: "%b %-d, %Y" -%}
25
+ {%- assign date_format = site.i18n.date.format | default: "%b %-d, %Y" -%}
26
26
  {{ page.date | date: date_format }}
27
27
  </time>
28
28
  {%- for author in page.author -%}
@@ -9,14 +9,46 @@
9
9
  <meta name="color-scheme" content="light"/>
10
10
  <meta name="referrer" content="strict-origin-when-cross-origin"/>
11
11
 
12
+ {% comment %}
13
+ No tenemos forma de hashear SASS aún, por lo que renovamos la caché
14
+ aplicando la hora de compilación del sitio. Es importante que los
15
+ CSS se renueven cuando se regenera el sitio, porque pueden contener
16
+ variables dinámicas (como personalización de colores y tipografía) o
17
+ minificarse distinto dependiendo del contenido.
18
+ {% endcomment %}
12
19
  <link href="assets/css/styles.css" rel="stylesheet">
13
- <script defer type="text/javascript" src="assets/js/pack.js"></script>
20
+
21
+ {% comment %}
22
+ Webpack. La configuración se pasa por variables de entorno, en
23
+ desarrollo hay que evitar el archivo .env (copiarlo de .env.example
24
+ si no existe.
25
+ {% endcomment %}
26
+ <link rel="preload" as="script" type="text/javascript" href="env.js" />
27
+ <script type="text/javascript" src="env.js"></script>
28
+ {% include_cached pack.html %}
29
+
30
+ {% comment %}
31
+ Agregar otras tipografías. Esto hace que las tipografías se carguen
32
+ lo más rápido posible y minimizar el tiempo en que se ven las del
33
+ navegador. En Firefox todavía no está soportado.
34
+
35
+ Fork Awesome lleva la hora de generación para poder renovarlo si
36
+ agregamos íconos nuevos, de lo contrario puede quedar cacheado para
37
+ siempre y les visitantes van a ver íconos rotos.
38
+ {% endcomment %}
39
+ {% include_cached preload_font.html font='assets/fonts/forkawesome-webfont.woff2' %}
40
+
41
+ <link rel="icon" type="image/svg+xml" href="public/favicon.svg">
42
+ <link rel="alternate icon" href="public/favicon.ico">
43
+ <link rel="mask-icon" href="public/favicon.svg" color="white">
44
+ <link rel="manifest" href="manifest.json">
14
45
 
15
46
  {% seo %}
16
47
  {% feed_meta %}
17
48
  </head>
18
49
  <body class="d-flex flex-column justify-content-between d-print-block min-vh-100">
19
- {% include navbar.html %}
50
+ {%- include_cached onboarding.html -%}
51
+ {%- include_cached menu.html active_cache_key=page.layout %}
20
52
  {% include_cached search.html %}
21
53
 
22
54
  <main class="flex-grow-1 container-fluid d-flex flex-column justify-content-start">
data/_layouts/page.html CHANGED
@@ -28,7 +28,7 @@ layout: default
28
28
 
29
29
  <p>
30
30
  <time class="dt-published" datetime="{{ page.date | date_to_xmlschema }}" itemprop="datePublished">
31
- {%- assign date_format = site.i18n.date | default: "%b %-d, %Y" -%}
31
+ {%- assign date_format = site.i18n.date.format | default: "%b %-d, %Y" -%}
32
32
  {{ page.date | date: date_format }}
33
33
  </time>
34
34
  {%- for author in page.author -%}
data/_layouts/place.html CHANGED
@@ -28,7 +28,7 @@ layout: default
28
28
 
29
29
  <p>
30
30
  <time class="dt-published" datetime="{{ page.date | date_to_xmlschema }}" itemprop="datePublished">
31
- {%- assign date_format = site.i18n.date | default: "%b %-d, %Y" -%}
31
+ {%- assign date_format = site.i18n.date.format | default: "%b %-d, %Y" -%}
32
32
  {{ page.date | date: date_format }}
33
33
  </time>
34
34
  {%- for author in page.author -%}
data/_layouts/post.html CHANGED
@@ -28,8 +28,8 @@ layout: default
28
28
 
29
29
  <p>
30
30
  <time class="dt-published" datetime="{{ page.date | date_to_xmlschema }}" itemprop="datePublished">
31
- {%- assign date_format = site.i18n.date | default: "%b %-d, %Y" -%}
32
- {{ page.date | date: date_format }}
31
+ {%- assign date_format = site.i18n.date.format | default: "%b %-d, %Y" -%}
32
+ {{ page.date | date_local: date_format }}
33
33
  </time>
34
34
  {%- for author in page.author -%}
35
35
 
@@ -1,13 +1,54 @@
1
- * {
2
- scroll-behavior: smooth;
3
- }
1
+ ////
2
+ /// Accesibilidad
3
+ /// @group Accesibilidad
4
+ ////
5
+
6
+ /// La navegación es suave. Esto hace que al navegar a elementos dentro
7
+ /// de la misma página no haga un salto, sino que haya una transición.
8
+ ///
9
+ /// Es especialmente útil en sliders.
10
+ ///
11
+ /// Sin embargo puede producir mareos a algunas personas.
12
+ * { scroll-behavior: smooth; }
4
13
 
5
- /*
6
- * Deshabilita animaciones si la usuaria las tiene deshabilitadas
7
- */
14
+ /// Aquí se aplica la opción `prefers-reduced-motion: reduce`, pero
15
+ /// SassDoc no la estaría mostrando.
8
16
  @media (prefers-reduced-motion: reduce) {
17
+ /// Si les usuaries prefirieron reducir las animaciones de los sitios,
18
+ /// deshabilitamos la navegación suavizada y las animaciones.
9
19
  * {
10
- scroll-behavior: auto;
20
+ scroll-behavior: auto !important;
11
21
  animation: none !important;
12
22
  }
13
23
  }
24
+
25
+ /// Utilizamos Axe para poder marcarnos cuáles elementos no cumplen con
26
+ /// parámetros de accesibilidad durante el desarrollo. Esta clase
27
+ /// muestra un borde rojo alrededor de los elementos inaccesibles y al
28
+ /// obtener el foco, muestra los mensajes de error generados por Axe.js.
29
+ ///
30
+ /// @link _packs/entry.js
31
+ .inaccesible {
32
+ outline: $red 1px solid;
33
+
34
+ @extend .position-relative;
35
+
36
+ &:focus::after {
37
+ @extend .position-fixed;
38
+ @extend .background-red;
39
+ @extend .white;
40
+ @extend .p-3;
41
+
42
+ left: 0;
43
+ bottom: 0;
44
+ width: 100vw;
45
+ font-size: 1rem;
46
+
47
+ word-wrap: normal;
48
+ line-break: auto;
49
+ white-space: pre-line;
50
+
51
+ /// El contenido se trae desde el ariaLabel del elemento.
52
+ content: attr(aria-label);
53
+ }
54
+ }