Restauration des anciennes URL des articles

Un des derniers points qui manquaient depuis la résurrection de ce blog était de faire refonctionner les anciennes URL des articles.

En effet, lors du passage sous Jekyll, d’une part le nommage des articles a été modifié (par défaut Jekyll les met en .html là où ma réécriture d’URL sous WordPress me les faisait juste finir par un /) et d’autre part j’ai changé de domaine, passant de wp.darathor.com à blog.darathor.net.

Il manquait donc deux opérations :

  1. rediriger l’ancien domaine vers le nouveau
  2. rediriger les anciennes URL vers les nouvelles

La première étape n’a rien de compliqué et se fait assez rapidement dans la configuration des VHOST d’Apache.

La seconde est un peu moins immédiate puisqu’il m’a fallu construire la table de correspondance des anciennes URL vers les nouvelles.

J’ai choisi comme stratégie de stocker une liste d’alias dans l’en-tête de chaque articles et de générer un fichier .htaccess à partir de ça.

Déclaration des alias

La déclaration des alias est assez simple et se limite à une liste d’URL relatives :

aliases:
- /?p=3
- /2007/05/01/ouverture-du-site/

L’avantage de fonctionner avec une liste d’alias en URL relatives c’est que cette même mécanique peut être ré-exploitée si je veux changer l’URL d’un article par la suite (notamment pour corriger une coquille).

Reste à l’alimenter dans mon cas de migration depuis WordPerss.

Le script de migration de WordPress vers Jekyll m’avait extrait une entrée de la forme wordpress_url: http://wp.darathor.com/?p=10 contenant une des formes d’URL proposée par WordPress. Par contre il ne s’agissait pas de la forme générée par la réécriture automatique de WordPress qu’il m’a fallu reconstruire pour aboutir aux deux alias ci-dessous. J’ai finalement choisi de garder les deux URL à chaque fois étant donné que les deux pointaient sur le contenu et que je n’aime pas les liens morts.

Génération du fichier .htaccess

Dans mon cas j’utilise Apache comme serveur web, donc je peux passer par un fichier .htaccess ce qui a un gros avantage : tout reste stocké dans le code versionné et déployable automatiquement sans aller toucher au VHOST.

Pour générer ce fichier j’ai procédé comme pour le robots.txt via une simple page nommée htaccess (sans extension sinon à la génération Jekyll la colle arbitrairement derrière le permalien) :

---
layout: null
permalink: .htaccess
---

ErrorDocument 404 /404.html

{% for post in site.posts -%}
{%- if post.aliases -%}
{%- for alias in post.aliases -%}
  Redirect 301 {{ post.alias }} {{ post.url }}
{% endfor -%}
{%- endif -%}
{%- endfor -%}

On retrouve donc l’en-tête avec un layout: null pour que le fichier généré ne soit pas habillé d’une structure HTML et un permalink: .htaccess indiquant le nom du fichier à générer.

Ensuite le contenu consiste en une simple boucle sur les articles avec à chaque fois une boucle sur les alias pour générer les redirections 301.

J’en ai également profité pour ajouter la ligne ErrorDocument 404 /404.html qui dit à Apache d’utiliser une page 404 personnalisée plutôt que la page par défaut.


Cartes Magic perso : Cycle Elenwen

On continue la série de republications de cartes Magic perso avec un cycle de cinq cartes parmi les premières que j'ai faites.

Erilerynlyg Elenwen
Erilerynlyg Elenwen (HD)

Réalisation

Comme d'habitude, avec GIMP.

L'illustration est trouvée sur deviantART : Kindred spirits par Anne Stokes alias Ironshod.

La texture je sais plus trop (oublié de noter :-/) ce que j'ai utilisé mais je sais que j'y ai appliqué plusieurs effets par dessus.

Idée

En tombant sur cette illustration je me suis dit que ce serait intéressant de faire un truc qui permette d'associer une créature à une autre. Il existe déjà les lytiques du bloc Tempête qui se transforment en auras mais je cherchais autre chose.

De là j'ai sorti une capacité originale : la symbiose, dont voici les règles :

  • La symbiose est une capacité activée des cartes de créature. "Symbiose avec les [type de créature] [coût]" signifie "[coût] : Attachez cette créature à la créature [type de créature] ciblée que vous contrôlez. Ne jouez cette capacité que lorsque les deux créatures sont dégagées et que vous pourriez jouer un rituel."
  • Une créature attachée à une autre via la symbiose est appelée "symbiote" celle à laquelle elle est attachée est appelée "hôte". Les deux créatures sont alors dites "en symbiose".
  • Un hôte ne peut avoir qu'un symbiote au maximum. Si une nouvelle créature devait lui être attachée par symbiose, rien ne se passe. Mis à part cette exception, les règle standard de l'attachement (701.2) s'appliquent.
  • Un hôte et son symbiote ont toujours le même contrôleur. Si un sort ou une capacité modifie le contrôleur de l'un des deux, il modifie également le contrôleur du second.
  • Un symbiote ne peut ni attaquer ni bloquer. Il peut par contre utiliser ses capacités activées et reste une créature à tout point de vue.
  • Lorsque des blessures sont infligées à un symbiote ou à son hôte, leur contrôleur peut rediriger tout ou partie de ces blessures de l'un vers l'autre.
  • Si un hôte quitte le champ de bataille, détachez son symbiote et engagez-le. Il ne se dégage pas pendant la prochaine phase de dégagement de son contrôleur.
  • Si un symbiote quitte le champ de bataille, engagez son hôte. Il ne se dégage pas pendant la prochaine phase de dégagement de son contrôleur.

Je me suis inspiré des règles sur les équipement et fortification pour essayer de faire un peu le tour de ce qu'il fallait prévoir.

Vue la place qui restait je me suis contenté d'une capacité assez simple lorsqu'elle est en symbiose (sinon, il aurait fallu virer le texte d'aide et sur une capacité perso c'est pas très cool).

Nom

Pour le nom du coup j'ai pioché dans le lexique de Sindarin sur le site Ambar Eldaron. J'ai essayé de combiner les parties du nom en suivant les indications que donne le site en la matière mais bon, faut pas trop espérer que ce soit parfait non plus, je suis pas linguiste et encore moins en Sindarin :D Puis bon, à vrai dire je pense pas que grand monde s'en souciera réellement :euh:

Les différents mots utilisés pour composer le nom sont :

wen
jeune fille
lug
dragon
eryn
forêt
elen
elfe
eria
élever

Pour donner enfin : Erilerynlyg Elenwen

D'autres cartes avec la symbiose

L'illustratrice ayant fait pas mal d'autres illustrations similaires, j'ai décliné l'idée pour chaque couleur (avec toujours du vert puisque ce sont des elfes).

Nestrilfaelyg Elenwen

Nestrilfaelyg Elenwen
Nestrilfaelyg Elenwen (HD)

Illustration : Secret Garden, par Anne Stokes alias Ironshod

Éléments linguistiques :

faelug
dragon (étincelant)
nesta
soigner

Lúthrillimlyg Elenwen

Lúthrillimlyg Elenwen
Lúthrillimlyg Elenwen (HD)

Illustration : Water Dragon, par Anne Stokes alias Ironshod

Éléments linguistiques :

limlyg
dragon-poisson
lútha
envoûter, enchanter

Baugrilmôrlyg Elenwen

Baugrilmôrlyg Elenwen
Baugrilmôrlyg Elenwen (HD)

Illustration : Soul Mates, par Anne Stokes alias Ironshod

Éléments linguistiques :

baugla
oppresser
môr
sombre, noir

Torthrilurlyg Elenwen

Torthrilurlyg Elenwen
Torthrilurlyg Elenwen (HD)

Illustration : Elegant Dragon, par Anne Stokes alias Ironshod

Éléments linguistiques :

tortha
contrôler
urlug
dragon de feu

Science-fiction et anachronismes #2

Il y a quelques années à la lecture du roman de science-fiction Les menhirs de glace (Icehenge an VO) de Kim Stanley Robinson, j’avais été frappé par certains éléments qui me semblaient particulièrement anachroniques dans le futur qu’il nous proposait au point d’en faire un article.

Cette fois-ci c’est le visionnage de deux séries de Star Trek : d’abord Enterprise (2001-2005), puis Deep Space Nine (1993-1999) dont je viens de finir la saison 2 qui m’ont fait tiquer sur certains points.

Je ne vais pas parler de la facilité qu’ils ont à traduire les langues ou d’autres éléments qui ont évidemment pour source le besoin d’éviter les longueurs dans la série. On n’est pas dupe une seconde sur le réalisme mais il y a une justification pratique : l’ensemble de la série perdrait de sa fluidité sans cela, ça fait partie des choses qu’il faut admettre (on est dans une fiction, pas dans un documentaire).

Mais il y a d’autres points qui ne sont pas nécessaires au bon fonctionnement de la série en général et me semblent juste relever d’anachronismes injustifiés.

Attention : ces séries étant anciennes, je vais donner des éléments du déroulement de certains épisodes sans masquage ou gros messages d’alerte. Vous êtes prévenus.

Les outils de communication

Dans Deep Space Nine, chacun des officiers de la station dispose de son « combadge ». Mes souvenirs de la série d’origine sont très vagues mais d’après Wikipédia, ils remplacent les « communicateurs » de l’époque.

On est donc sur des appareils qui ne permettent que le la communication audio (pas d’images notamment) plus certaines données comme la localisation. On est donc bien sur des versions diminuées de nos ordiphones actuels. Quelque part, on peut considérer que ça ne tapait pas trop à côté puisqu’on est effectivement allé dans cette direction (même si dans la pratique on est allé bien plus loin et plus vite qu’ils ne l’envisageaient).

Mais là où ça commence à vraiment être bizarre c’est dans Enterprise qui se passe un siècle avant la série d’origine et deux avant Deep Space Nine. Là la communication dans le vaisseau est assurée par un réseau de bornes murales qui relaient les messages vocaux auxquels on peut répondre après avoir pressé un bouton…

J’imagine que l’idée était de caser un système moins évolué que les communicateurs et combadges des séries chronologiquement postérieures et en cela ça se tient. Cependant ce n’est vraiment pas très crédible par rapport à la réalité de ce qui s’est passé entre temps et qui était déjà bien engagé à l’époque où a été tournée Enterprise (2001-2005) : le téléphone portable puis l’ordiphone se sont rapidement généralisés.

Du coup imaginer qu’on revienne en arrière avec un réseau fixe dans le vaisseau parait assez difficile. Surtout avec tous les petits appareils qu’ils trimbalent et permettant de magiquement tout analyser ou traduire des milliers de langues en temps réel… Qu’ils n’aient pas intégré un appareil de communication sous une forme ou une autre est des plus bizarres et ne s’explique que parce qu’ils ont dû se retrouver piégés entre ce qui avait déjà été fait dans les autres séries (chronologiquement postérieures et donc technologiquement plus avancées) et ce qui s’est passé entre temps dans la réalité.

L’irréfutabilité de l’enregistrement

La bascule ne s’est pas encore faite dans notre époque actuelle mais elle s’annonce de plus en plus : comment peut-ont imaginer s’assurer qu’un enregistrement est véridique ? Pour une communication en temps réel c’est plus simple, on peut imaginer des signatures authentifiant les interlocuteurs comme on le fait actuellement avec les mails quand on veut certifier leur émetteur et la non-altération du contenu. Mais on ne certifie en aucun cas l’honnêteté de l’interlocuteur, juste de la transmission.

Dans l’épisode 13 de la seconde saison de Deep Space Nine (Annihilation en VF, Armageddon Game en VO), les représentant d’une race extra-terrestre rapportent un enregistrement vidéo censé relater la mort de deux membre de la station. Cet enregistrement est accueilli comme évidemment vrai par le commandant.

La seule à le mettre en doute est la femme de l’un des deux supposés morts qui croit déceler une incohérence dans le comportement de son mari (qui ironiquement s’avère en plus faux à la fin de l’épisode). À aucun moment les responsables de la station ne remettent en cause la véracité de l’enregistrement. Ils remettent fréquemment en cause les témoignages oraux mais pas les enregistrements. Notamment ils se fient aveuglément à un élément pourtant facilement falsifiable : l’horaire indiqué dans l’enregistrement.

Déjà actuellement, l’authentification des preuves que ce soient des enregistrement vidéo ou vocaux ou plus généralement des documents numériques est de plus en plus difficile. De nombreuses manipulations peuvent être faites de façons de plus en plus indétectable : changer une métadonnée comme la date est généralement assez simple et difficilement détectable.

On imagine donc bien qu’au 23e siècle, tandis que l’humanité parcourt la galaxie, les techniques de manipulation d’image ont nécessairement progressé également. Si à notre époque les premières résurrections d’acteurs décédés par images de synthèses restent perfectibles, on imagine bien que 3 siècles plus tard ce sera plus vrai que nature.

Il parait donc plus qu’étrange que la question de la falsification ne se pose même pas avant l’intervention de l’épouse. Certes les extra-terrestres en question sont bien censés être plus ou moins des alliés mais bon quand on vous annonce que deux de vos experts sont morts (suite à une erreur de manipulation de l’un d’eux en plus) alors qu’ils étaient sur le point de finir une mission sans danger il semble naturel de se poser des questions. Et là rien : l’enregistrement est une preuve évidente. Point.

L’impasse de la biométrie

Dans l’épisode 25 de la seconde saison de Deep Space Nine (Tribunal aussi bien en VO qu’en VF), Miles O’Brien est accusé d’avoir volé des armes. Notamment l’ordinateur relève que c’est lui qui est le dernier à être entré dans le dépôt. La preuve ? C’est sa voix qui a commandé l’ouverture de la porte.

Bon là au moins la preuve est mise en doute et rapidement ils remarquent en analysant l’enregistrement que la voix a été trafiquée. Ou plutôt que la phrase prononcée est un montage réalisé à partir de mots distincts enregistrés.

Mais un système de sécurité authentifiant les gens à leur voix ? Vraiment ? C’est tellement évidemment facile à abuser, que ce soit en rejouant un enregistrement véridique ou en en construisant un, que même de nos jours on n’essaie pas d’utiliser un truc aussi faible.

Intrinsèquement la biométrie est peu fiable pour de l’authentification et ce pour deux raisons principales : d’une part les données biométriques sont publiques ou récupérables assez facilement et d’autre part elles sont non-modifiables (enfin y a toujours moyen de recourrir à la chirugie pour certaines d’entre elles mais c’est assez lourd pour une donnée fuitée dont la remplaçante sera de nouveau facilement accessible).

Même actuellement quand on met en avant la biométrie pour de l’authentification on a la décence de prendre un truc un peu moins facile à falsifier que la voix (genre l’iris ou les empreintes digitales).

Là on est censé avoir fait des progrès énormes mais on reste sur de l’authentification vocale pour protéger l’accès à un dépôt d’armes… Ça laisse songeur.


Carte Magic perso : Troisième main

On continue la série de republications de cartes Magic perso avec une carte orientée humour qui aurait plutôt sa place dans une extension type Unglued. Elle aussi était une participation à un jeu FC mais je n'ai pas retrouvé le thème.

Troisième main
Troisième main

Bon, j'avoue c'est loin d'être ma plus réussie mais bon, je la poste quand même parce que bon, l'idée de base me plait bien :p

Réalisation

Comme d'hab : GIMP + le xcf de NorthNikko (un peu retouché par moi à force). L'illustration n'est pas idéale mais après une heure de recherches infructueuses, j'ai fini par me rabattre l'illustration OOOK par Berilia. Enfin, la texture : il s'agit de pramos03 par Lwsypher.

Rien de transcendant dans la réalisation mais à force de chercher désespérément une illustration qui convienne, j'avais plus le courage de faire un truc recherché pour le reste :tired: J'envisageais de lui coller des cartes dans une main et le pied visible mais j'ai pas eu le courage... peut-être un jour je prendrai le temps de le faire, un jour où je me sentirai plus motivé qu'hier ^^

Idée

L'idée m'est venue comme ça qu'on pouvait faire un truc marrant avec les pieds :D On a donc là une carte fun qui, si l'on est agile de ses pieds permet de piocher 7 nouvelles cartes ne comptant pas dans la limite de cartes en main (normal, elles ne sont pas dans la main mais dans le pied :smile:).

Après pour habiller un peu le tout, je l'ai tournée en références aux singes, dont les pieds sont habiles que les nôtres et qui renforçaient l'ambiance fun de la carte :p C'est pour ça que j'ai collé une touche de vert en plus du bleu, même si la capacité n'y fait pas des masses référence.

Pour le texte d'ambiance, en bon fan l'œuvre de de Terry Pratchett, j'ai hésité un moment à mettre juste "Ook !" mais bon finalement j'ai fait un peu plus long ^^

Bon après y a un gros point noir à ma carte (comme à certaines autres participations d'ailleurs) : le pied n'est pas à proprement parler un permanent, du coup c'est pas complètement dans le thème, mais bon j'avais pas d'autre idée... :-/

Voilà voilà :o


Moteur de recherche dans un site Jekyll

La problématique

Dernier des gros points noirs relevés lors de ma bascule sur Jekyll : l’absence de moteur de recherche.

Forcément quand le site est statique, c’est plus compliqué de mettre en place un moteur de recherche. Il y a plusieurs approches possibles :

  • faire une partie dynamique côté serveur pour la recherche : bof, le but c’est d’avoir maintenance côté serveur, donc non
  • faire appel à une API tierce qui ferait l’indexation puis la recherche : bof aussi, ça permet certes de rester statique côté serveur mais délocaliser la chose n’est pas mieux (en plus ça veut dire maintenance sur l’utilisation de l’API) donc non
  • déléguer complètement à un moteur externe type Google Search : ça existe sur certains sites (quoique ça fait un moment que je l’ai plus vu) sous la forme d’un formulaire de recherche redirigeant sur Google avec une recherche de type site:monsite.com ...… c’est mieux côté maintenance mais pire côté délocalisation puisqu’on quitte carrément le site, donc non

Reste la dernière : faire la recherche directement dans le navigateur en JS à partir d’un index fourni, solution finalement retenue.

Bon, c’est loin d’être parfait comme concept : ça ne passe évidemment pas à l’échelle notamment mais ce site reste un blog perso donc la volumétrie de devrait pas exploser…

L’index fait environ 500ko avec mes 156 articles actuels (représentant un peu plus de 10 ans) donc ça reste jouable, même si j’ai augmenté mon rythme ces derniers temps (notamment à cause des republications). Dans tous les cas on reste loin des pages d’accueil avec des gros carrousels d’images à 2Mo chacune qu’on trouve sur certains sites (notamment e-commerce) et ce n’est de toutes façons chargé que sur la page de recherche.

Donc c’est réaliste dans mon cas et vous pouvez le tester via le champ de recherche dans la colonne de droite.

Solution existante et adaptations

Je suis parti de cet article proposant une solution basée sur la bibliothèque Lunr mais comme souvent c’était loin d’être satisfaisant de base :

  • forcément c’est en anglais, donc fallait au moins traduire
  • ça ne permet pas de placer le champ de recherche sur toutes les pages (à moins d’inclure le code de recherche sur toutes les pages aussi, ce qui est exclus)
  • visuellement le rendu ne me convenait pas du tout
  • toutes les pages sont indexées, y compris les pages de catégories par exemple qui ne sont que des regroupements d’articles

Du coup j’ai réorganisé les choses différemment en :

  • séparant l’index dans un fichier JS à part
  • modifiant le formulaire pour qu’il fasse un simple GET vers une page dédiée au résultat de recherche
  • modifiant le JS pour que le terme à rechercher soit cherché dans l’URL
  • ajoutant dans l’en-tête des pages devant être indexées un paramètre searchable: true

La section suivante détaille la marche à suivre pour intégrer tout ça sur votre site.

Mise en œuvre

La bibliothèque Lunr

À récupérer ici et à ajouter dans le dossier assets/js.

Le code JS utilisant Lunr

Dans un fichier assets/js/search.js :

(function (window) {
	window.onload = function () {
		var idx = lunr(function () {
			this.ref('id');
			this.field('title');
			this.field('body');

			window.searchIndex.forEach(function (doc) {
				this.add(doc)
			}, this)
		});

		var resultsElement = document.getElementById('search-results');
		var HTML = '';
		var term = getQueryString('q');
		if (term) {
			document.getElementById('search-field').value = term;
			var results = idx.search(term);
			if (results.length > 0) {
				var plural = results.length > 1;
				HTML += '<p>' + results.length + ' résultat' + (plural ? 's' : '') + ' trouvé' + (plural ? 's' : '') + ' pour la recherche « ' + term + ' » :</p> <ul>';
				for (var i = 0; i < results.length; i++) {
					var result = window.searchIndex[results[i]['ref']];
					var url = result['url'];
					var title = result['title'];
					var date = result['date'];
					var body = result['body'].substring(0,160) + '...';
					var type = result.type === 'post' ? 'Article' : 'Page';

					HTML += '<li class="search-result"><p class="metadata"><a href="' + url + '" class="title">' + title + '</a>';
					HTML += ' <span class="type">' + type + '</span>';
					if (date) {
						HTML += ' <span class="date">publié le ' + date + '</span>';
					}
					HTML += '</p><p class="summary">' + body + '</p></li>';
				}
				HTML += '</ul>';
			}
			else {
				HTML += '<p>Aucun résultat trouvé poru la recherche « ' + term + ' ».</p>';
			}
		}
		else {
			HTML += '<p>Aucun terme à rechercher.</p>';
		}
		resultsElement.innerHTML = HTML;
	};

	/**
	 * Get the value of a query string.
	 * @param {string} field The field to get the value of
	 * @param {string=} url The URL to get the value from (optional)
	 * @return {string} The field value
	 */
	var getQueryString = function (field, url) {
		var href = url ? url : window.location.href;
		var reg = new RegExp( '[?&]' + field + '=([^&#]*)', 'i' );
		var string = reg.exec(href);
		return string ? string[1] : null;
	};
})(window);

Je n’ai pas cherché à extraire le rendu HTML du résultat de recherche, donc il faudra directement modifier ce fichier pour l’arranger.

Le fichier d’index : search-index.js

Dans un fichier search-index.html à la racine du projet :

---
layout: null
permalink: search-index.js
---

(function (window) {
  {%- assign counter = 0 %}
  window.searchIndex = [{% for page in site.pages %}{% if page.searchable %}{
    "id": {{ counter }},
    "url": "{{ site.url }}{{ page.url }}",
    "type": "page",
    "title": "{{ page.title | replace: '"', ' ' }}",
    "body": "{{ page.content | markdownify | replace: '.', '. ' | replace: '</h2>', ': ' | replace: '</h3>', ': ' | replace: '</h4>', ': ' | replace: '</p>', ' ' | strip_html | strip_newlines | replace: '  ', ' ' | replace: '"', ' ' }}"{% assign counter = counter | plus: 1 %}
  }, {% endif %}{% endfor %}{% for page in site.posts %}{
    "id": {{ counter }},
    "url": "{{ site.url }}{{ page.url }}",
    "type": "post",
    "date": "{{ page.date | date: '%d/%m/%Y à %R' }}",
    "title": "{{ page.title | replace: '"', ' ' }}",
    "body": "{{ page.content | markdownify | replace: '.', '. ' | replace: '</h2>', ': ' | replace: '</h3>', ': ' | replace: '</h4>', ': ' | replace: '</p>', ' ' | strip_html | strip_newlines | replace: '  ', ' ' | replace: '"', ' ' }}"{% assign counter = counter | plus: 1 %}
  }{% if forloop.last %}{% else %}, {% endif %}{% endfor %}];
})(window);

Il est possible de modifier ce fichier si vous voulez ajouter des informations à l’index (par exemple des données complémentaires pour l’affichage des résultats).

La page de résultat de recherche

Dans un fichier search.md à la racine du projet :

---
layout: page
title: Recherche
---

<script src="/assets/js/lunr.js?v={{ site.time | date: '%s' }}" type="application/javascript" async="async"></script>
<script src="/assets/js/search.js?v={{ site.time | date: '%s' }}" type="application/javascript" async="async"></script>
<script src="/search-index.js?v={{ site.time | date: '%s' }}" type="application/javascript" async="async"></script>

<div id="search-results">Recherche en cours...</div>

L’entrée layout est à adapter en fonction de ce que vous avez défini sur votre site.

Le formulaire de recherche

Il reste à intégrer le formulaire de recherche là où vous souhaitez de voir apparaitre :

<form action="/search.html" method="get" class="search-form">
  <p>
    <input id="search-field" type="text" name="q" maxlength="255" value="" />
    <button type="submit" title="Lancer la recherche"><img src="/assets/img/search.svg" alt="Lancer la recherche" /></button>
  </p>
</form>

Pages indexables

En l’état seuls les articles seront indexés. Il reste donc à ajouter searchable: true dans l’en-tête de chaque page que vous souhaitez indexer.