Skip to main content

Hello ! This is my blog powered by Known. I post articles and links about coding, FOSS, but not only, in French (mostly) or English (if I did not find anything related before).

phyks.me

github.com/phyks

phyks@phyks.me

 

Localizing a webapp with webL10n.js

3 min read

I am currently working on a Velib webapp. With Élie, we modularized everything so that the backend API can be edited easily, and adapted to any other bike sharing system, hence we wanted it to be easily localizable and looked for solutions compatible with as many browsers as possible. We finally chose webL10n.js. Here are some explanations about it and how to use it.

Why webL10n.js?

First thing is: why choose webL10n.js instead of anything else? We found basically four solutions: webL10n.js, L20n.js, Jed and a modified version of webL10n.js used in Gaia.

Jed takes a really different approach and, especially as we are not really familiar with localizing content, we found it more difficult to use and integrate.

The three others take a really simple approach. They use extra data-* attributes on any tag to replace on the fly the textContent of the node by a translation found in a formatted file. It is really easy to integrate, use and tweak. They support advanced features such as pluralization, HTML modifications, responsive localization (to use a different localization file on small screens), etc.

WebL10n.js and the modified version in Gaia are basically the same, except that the one in Gaia dropped hacks to add support in some old browsers such as IE6. Plus webL10n is in a separate git repo which is easy to track, so I'd rather go with this one. But the documentation is not really complete and the associated MDN wiki page is outdated. Hence this blog post :) Don't worry about the lack of recent commits on webL10n.js, it is stable and usable (and still maintained and supported by kaze).

L20n.js is the latest Mozilla project aiming at replacing webL10n.js. I had many problems with it, because the API keeps moving, and no doc is in sync with the code. Downloadable version exposes a totally different API than the one in the git repo, and the doc is not really helpful concerning which version should be considered stable. Plus the l20n file format is really weird and I'd rather not reinvent the wheel and go with standard properties file to ease translation for contributors.

Demo and extra infos

For more informations, you can refer to the README.

For an app using it, you can have a look at our VelibFxos webapp, espcially this folder. You can also see it in your browser at https://velib.phyks.me/ (under heavy work in progress, so might break from time to time).

Note: Note that there is a bug when mixing pluralization and innerHTML, which can be worked around. See this Github issue.

EDIT: Since I initially wrote this article, I came across Polyglot.js, a JS library by Airbnb, which does exactly this. It looks really nice and trustable, especially since it is backed by Airbnb which is heavily using it. One major drawback is that is uses a non-standard format for translations, instead of a po file or a properties file. But it could be easy to plug such a parser into it. It supports basically the same features as webl10n.js, except that it only has a JS API, without support for extra data- parameters. This is ok if you render your templates in JS (using React or Angular for instance), but I find it more difficult than webl10n.js to use in other cases.

, ,

 

Blocking JavaScript on a per API basis

3 min read

JavaScript is widely used on the Internet, and living without it can be a real pain. However, JavaScript use raises some security concerns, in particular because some JavaScript APIs can be really sensitive. Indeed, WebRTC calls can be used to detect your real IP even the private one, on your network, JavaScript can interact with the clipboard, … Clipboard API can be blocked in about:config in Firefox for instance, but that is not the case for every such API. Hence, I wanted to have a look at what can be done to prevent the use of such sensitive APIs.

Plus, in my opinion, NoScript is not really usable, as it blocks way too much things and you end up clicking on "Allow this website" on basically every website to be able to use them. Then, the security benefit from using NoScript gets very low.

I found a way (most a PoC than a real usable thing) to selectively block some APIs, through NoScript surrogate scripts and Object.defineProperty. For instance, to block the WebRTC PoC previously linked, one can add

noscript.surrogate.test.replacement = Object.defineProperty(window, 'mozRTCPeerConnection', {get: function() { console.log('rtc'); return function() {}; }, set: function() {}});
noscript.surrogate.test.sources = @^(?!chrome:)[0-9A-Za-z-]+

in his about:config.

The Object.defineProperty syntax is a bit weird in this case, as I have to return a function in both the getter and the setter. I did not find any specific reason for doing it, and this is the only way I found to block this property. If you have any idea, please let me know, as I do not like to not understand this problem, and do not like much having something that could potentially break at any time. For the full discussion about this NoScript surrogate script, please refer to the NoScript forum.

Next steps would be to implement it as a standalone plugin, in order not to use NoScript and have a more user-friendly user interface (list all the sensitive APIs, one-click to enable / disable them and reload the page…), or better implement it as a Privoxy external filter so that this protection will not be in the browser itself, but in a different layer, to increase security. I will work on it as soon as I find some free time, but feel free to do something and share in the mean time if you are interested in the topic!

 

Quick comparisons of solutions for 3D cross-platform (mobile) development

9 min read

I spent some time lately comparing available development toolkits for 3D games / apps on mobile platforms (mostly for hobby / indy apps). I do not want to have to adapt too much my base code depending on the target platform, and I was then looking at a toolkit to write most of the code once, and be able to build the app for various platforms on the market. My use case is: sufficient 3D engine (not necessarily a high end thing, just the basics to be able to write 3D apps decently. I consider Three.js as sufficient for my needs for instance). I am working on Linux, so the ability to dev on Linux would be a real plus. Of course, it should be as cheap as possible :) and finally, I am paying much attention at the EULA and licenses, as I do not want to force my users to send “anonymous” statistics and I do not want my app to need extra (and useless) permissions.

Note: I did not test these toolkits deeply, and I am just reporting here what I found while playing a bit with them and comparing the features, licenses and requirements. I only included toolkits that suit my needs and some missing toolkits may be missing just because they do not match my needs.

Note: I need to be cross-platform, which means I want to be able to target both Android, iOS and Firefox OS. Then, I need a WebGL export ability (for Firefox OS). Anyway, being able to have a WebGL export is a plus as this means you can build a webapp, which is interesting for my use cases.

 

Cordova

First toolkit I had a look at was Cordova. It allows you to write pure web apps (using standard HTML / CSS / JS and providing some extra APIs to extend the available APIs, for bluetooth for instance) and to package them into native apps distributed through the market. What it does is basically adding a wrapper around your web app to render it outside a browser, using the offered web abilities provided by webviews on iOs and Android. Writing a web app is really super easy, and then having a first working prototype using Cordova is super fast. Cordova runs on Linux without any problems. Cordova is completely free of charge.

It works pretty well for 2D graphics and basic applications (but it needs some extra permissions as it uses a web view, even if it is not communicating over internet). But when it comes to 3D graphics, using WebGL, you will be in troubles. Indeed, the webview in Android 4.x is using an old version of Chrome, even if you install the latest Chrome on your mobile. Then, you will not be able to use WebGL as it is simply not supported, unless you use some hack to actually use a more recent Chrome version, using Crosswalk for instance. On iOS, this is even worse as WebViews prior to iOS8 do not support WebGL (and as far as I know, there is no alternative which will be both stable, reliable and will pass through the reviewing process of the appstore). This mean that you will not be able to target iPhones prior to (and including) iPhone 4, and iPad 1, which in my opinion is a real problem.

Unreal Engine

Second option is to use the Unreal Engine 4. It is a complete 3D game engine, including many tools to build 3D apps that you can deploy on many platforms (both desktop, web and mobile). You can code in C++ with it, and script using many visual tools. It includes dedicated APIs for advanced features such as Virtual Reality (VR) and may sound overkill.

You can dev using Windows and Mac (officially supported), but not Linux (at least, not officially). However, it seems that the dev editor can be installed on Linux at the cost of a bit of hacking, and this should be even easier to install in the near future as there seems to be a developping Linux community.

Unreal Engine charges you with 5% royalties passed the first 3k$.

Here are some relevant EULA fragments:

12. Hardware and Usage Data

You acknowledge that, as a default setting, the Engine Code will collect and send to Epic anonymous hardware and usage data from end users of Products. This functionality is used by Epic to improve the Engine Code. You may modify the Engine Code under the License to turn off that functionality in your Product, or you may include in your Product the capability for your end users to turn off that functionality in the Product.

and

You agree to keep accurate books and records related to your development, manufacture, Distribution, and sale of Products and related revenue. Epic may conduct reasonable audits of those books and records. Audits will be conducted during business hours on reasonable prior notice to you. Epic will bear the costs of audits unless the results show a shortfall in payments in excess of 5% during the period audited, in which case you will be responsible for the cost of the audit.

The second one is a standard one, as you have to pay royalties depending on your revenues. But the first one is really concerning, as by default Unreal Engine will track your users and send anonymous statistics (thus requiring extra and unneeded permissions and raising privacy concerns). However, once you are aware of it, you can freely modify your app to prevent this, according to the EULA, so this is not a big deal in the end.

Unity

Latest solution I found (used by Monument Valley for instance) is the Unity game engine. The personal license is sufficient in most of the cases, and is free to use up to 100k$ gross revenue. The dev tools are available on Windows and Mac, but there is no Linux version (and no hacky way to get it in Linux).

Here are some relevant fragments from EULA as well:

(c) users will be required to complete a user survey to activate the Software. Unity Pro users who are not eligible to use Unity Personal may not develop and publish Licensee Content for the iOS and Android platforms without purchasing the applicable Unity Pro Add-On Product license. Unity may monitor your compliance with and enforce these restrictions and requirements including but not limited to monitoring the number of downloads of your Licensee Content and any available revenue estimate data.

This one is not really clear, and I am not really sure of what it really implies. However, according to http://unity3d.com/legal/eula and https://unity3d.com/legal/privacy-policy, it seems to imply that statistics are sent and that you cannot avoid it, even in the pro version.

We also include certain device data collection in the runtime of the Software which is incorporated into the applications you create with the software. You should be sure that your privacy policy explains to your players the variety of technical information that is collected and shared with third parties like Unity.

and

Q: I play a game built with Unity software, what should I know?

A: Unity has probably collected some or all of the following information about your device: Unique device identifier generated from the device MAC/IMEI/MEID (which we immediately convert into a different number using a one way hash); IP address; Device manufacturer and model; the operating system and version running on your system or device; browser type; language; the make of the CPU, and number of CPUs present; the graphics card type and vendor name; graphics card driver name and version (example: "nv4disp.dll 6.10.93.71"); which graphics API is in use (example: "OpenGL 2.1" or "Direct3D 9.0c"); amount of system and video RAM present; current screen resolution; version of the Unity Player; version of the Unity Editor used to create the content; a number describing whether the player is running on Mac, Windows or other platforms; and a checksum of all the data that gets sent to verify that it did transmit correctly; application or bundle identification ("app id") of the game installed. Some Unity developers use Unity’s analytics and ad services which collect additional information. See FAQs on Unity Analytics and Unity Ads below.

Q: That seems like a lot of data, why so much?

A: We try to limit the collection of this information from any one player or device; however, certain operating systems do not permit us to note that the info has already been collected. This means that the data may be sent to Unity each time you start the game. We use the information to make decisions about which platforms, operating systems and versions of them should be supported by our game development software. We aggregate this data and make it available to developers at stats.unity3d.com. This data helps us improve our Services and helps developers improve their apps.

8. Your choices about Unity’s collection and use of your information

You always have the option to refrain from using the Service or to discontinue using the Service if you do not want information collected about you.

They also explictly says in the FAQ that there is no opt-out, and the anonymous stats are indeed browsable at http://stats.unity3d.com/mobile/. In conclusion, contrary to Unreal Engine, I do not think you can easily prevent the engine from sending anonymous statistics, which is a pity in my opinion. Moreover, there are a number of threads talking about extra permissions required by Unity (such as network access to send the statistics) and there seems to be no way to not require those permissions and to still conform to the EULA: http://answers.unity3d.com/questions/663197/how-to-prevent-unity-from-adding-permissions-to-an.html and http://forum.unity3d.com/threads/extra-permission-needed-in-android.295556.

 

EDIT: For 2D graphics, this StackOverflow post might be interesting.

EDIT2: I also found EdgeLib, Emo but they do not support web export.

EDIT3: CryEngine does support also Linux, Windows, iOS and Android, but not the web, and it is very expensive (license at 10$ per month).

EDIT4: Gameplay3D is also an open-source toolkit that can be used for cross-platform dev, written in C++, but it does not support emscripten officially for JavaScript output (and they do not plan on supporting it).

, ,

 

Proof-of-concept: BloomySearch, a (JavaScript) client-side search engine for static websites

6 min read

Overview

Many websites and blogs are statically generated and the webserver only serves static files. It is the case of many doc websites and more and more blogs, starting from this one, as Jekyll / Pelican develops.

This is really useful to reduce the complexity of the website and the load on the webserver. All the complex logic is done at the generation.

However, this also means you do not have dynamic pages on your website to handle search queries. Then, you are left with two (or three) choices :

  1. Use an external search engine, such as an embedded Google search box. This raises some privacy concerns and make you depends on an external service.
  2. (Use a JS search engine such as the filters provided by Angular.JS. This only works on the displayed content, and is not a real solution).
  3. Stop worrying about search engine on your website and let the users wget-ing and grep-ing your website on their computers. This is not the most user-friendly solution…

There are a couple of solutions around, mostly based on Lunr.js which generates an index from the articles available, and use this index for fulltext search. This is the best solution I found so far but it is still not perfect. Although there is a stemmer and an index generation to reduce the amount of data to be transferred, the data is not stored in a very efficient way, and the full index is sent as JSON. An example implementation for Jekyll is available through the jekyll-lunr-js-search plugin.

I had the idea of a client side search engine in mind for a while, but was facing the same problem as Lunr.js: how not to send a full (very large) index over the network to every single client ? Not having an optimized data structure would basically mean sending twice the content of the website to the client. It may not be a practical problem nowadays, as transfer speed is not always the limiting resource, but it is still not to be considered as a good practice, in my opinion, especially if your website might be accessed from mobile devices.

I came accross this article from Stavros Korokithakis and thought something similar could be achieved directly in the browser. Instead of using a standard dictionary to store the index, this article proposes to use a Bloom filter per article. Bloom filters are very interesting probabilistic structures which can store whether an element is or not in a set, with a fixed number of bits. It can return false positives: if an element is in the set, it always returns True, but if an element is not in the set, it may say it is actually in, with a small probability. Wikipedia page on the subject has all the necessary stuff to understand these data structures.

I wrote it in the context of my blog, which means a Python script to generate the index at pages generation, and a client side search engine in JavaScript, running in browser.

A demo is available here. It contains all the articles of my blog, as of writing this article, totalizing 160k characters, and only 7kB of index, allowing 10% of false positives, which may be a bit too much for a really reliable search engine. Reducing the error rate will lead to an increase in the index size (11kB for 1% of false positives and the same amount of characters).

Details of the implementation

As JavaScript is not the easier language to use for hashing and binary data manipulation, I started by implementing the client side search engine. Then, it would be easier to adapt the Python code to the JS lib than doing the contrary. Actually, I found this bloomfilters.js library from Jason Davies which was doing most of the job and did not need many modifications. I edited it a bit to support a construction with a capacity and an error_rate, instead of an explicit number of bits and times to apply the hashing function. This forked version is available here.

Then, I reimplemented this library in Python, to generate readable Bloom filters for the JavaScript script.

Server side

The generation script takes every articles in a given directory and for each of them:

  1. It gets a set of all the words in this article, ignoring too short words.
  2. It applies Porter Stemming Algorithm to reduce drastically the number of words to keep.
  3. It generates a Bloom filters containing all of these words.

Finally, it concatenates all the per article Bloom filters in a binary file, to be sent to the client. It also generates a JSON index mapping the id of the Bloom filter in the binary file to the corresponding URL and title for each article.

Client side

Upon loading, the JavaScript script downloads the binary file (see this MDN doc for more details) containing the Bloom filters and the JSON index, and regenerate BloomFilters on the client side.

When the client searches for something, the JavaScript script splits the query in words and iterate over the Bloom filters to search for the words. That's it =)

(Fun) facts found while reimplementing the Bloom filters library in Python

First problem I had to deal with : the difference between JavaScript Number type and Python int. JavaScript has only one type for all numbers (int or floats) and it is Number (see this SO thread). They are 64-bit floating point values, with a magnitude no greater than 253. However, when doing bitwise operations, they are casted to 32 bits before doing the operation. This is something to take care of, because Python's int can be 64 bits (http://legacy.python.org/dev/peps/pep-0237/). Then, when a bitwise operation overflows in JavaScript, it may not overflow the same way in Python.

The solution to this problem was to use ctypes.c_int in Python for bitwise operations, as proposed here.

Another problem was the difference between modulo behaviour with negative numbers in Python and in JavaScript. Unlike C, C++ and JavaScript, Python's modulo operator (%) always return a number having the same sign as the divisor (Source). Then, we have to reimplement the C behaviour in a modulo function in Python.

Finally, there was no “shift right adding zeros” (logical right shift) in Python, contrary to JS, see this SO thread.

,

 

Mon lecteur RSS idéal

21 min read

EDIT : J'ai repris quelque peu le commentaire de FreshRSS, après discussion avec son auteur. J'avais raté certaines options en particulier.

EDIT 2: Suite à quelques retours sur cet article, je tiens à préciser que la première partie de l'article (« Panorama de ce qui existe ») est volontairement courte et caricaturale. C'est une compilation caricaturale de réflexions que j'ai entendues, et je ne m'étends volontairement pas dessus, pour ne pas allourdir inutilement cet article qui vise d'abord à présenter les points qui me semblent importants pour mon lecteur de flux RSS idéal.

Attention, cet article est un bon pavé et il est sûrement plein de répétitions… :)

Sam&Max ont écrit récemment sur leur moteur idéal. Le moteur de blog est un réel problème, et j'adhérerais immédiatement à un moteur de blog qui satisfasse leurs critères (mais bon, pour l'instant ma solution maison patchée de partout fonctionne pas trop mal :). En revanche, un autre point mérite une bonne réflexion et pourrait être grandement amélioré et modernisé : le lecteur RSS.

J'utilise actuellement Leed sur mon serveur. J'en suis globalement satisfait, mais certains points m'agacent et ne sont pas résolus, au fil des versions. Pourtant, après avoir fait le tour des solutions existantes, c'est la solution la plus fonctionnelle que j'ai trouvée… Je profite donc de ce billet pour dresser un bilan de ce que j'ai vu passer sur les lecteurs RSS et ce que je voudrais trouver dans mon lecteur RSS idéal.

Panorama de ce qui existe

Tout d'abord, sebsauvage a fait il y a quelques temps un petit tour d'horizon des solutions de lecteurs RSS à héberger. Je vais faire court, au risque de m'attirer les critiques :

Leed
On attend le support du multi-utilisateur depuis un moment, il utilise mysql_ qui est déprécié, base MySQL obligatoire, quand même assez lourd, une licence non libre (CC BY SA NC), des développeurs principaux indisponibles (le wiki est globalement HS pour l'instant), un thème de base très moche, pas si simple à installer pour Mme Michu, des thèmes qui sont quand même limités, et bloqués par le dépôt principal
KrISS Feed
C'est moche, pas fonctionnel. Je ne me suis pas attardé sur le reste, qui semble assez standard.
FreshRSS
Il peut gérer beaucoup d'articles (100k annoncés sur le site). C'est pas très bô (beau / ergonomique / efficace) non plus, trop compact (notamment sur smartphone, quand on a des gros doigts :), et les infos importantes ne sont pas mises en valeur (à mon avis, les flux sont les éléments principaux, à mettre en valeur ; sur FRSS, mon œil est beaucoup plus attiré par les dossiers et les boutons). C'est aussi compliqué à installer (base MySQL, même si c'est pas si compliqué, Cron manuel, instructions dans le README que ne lit pas Mme Michu), et cela risque de bloquer Mme Michu… Ses avantages par contre : il supporte très bien la charge, et l'intégration de Mozilla Persona est originale. Il a aussi de nombreuses possibilités, pour peu qu'on fouille un peu les menus de configuration.
Aeres
Site HS, mais ça a l'air très moche aussi.
Miniflux
Seul concurrent sérieux, à la vue du site. De très bonnes idées, comme le full content et la suppression des trackers à la volée, mais quand on ouvre la page de démo, c'est moche… et inutilisable ce qui est vraiment dommage pour un script qui est hébergé contre paiement. C'est minimaliste, trop minimaliste. Les liens pour marquer comme lus, non lus, supprimer etc sont invisibles, le texte de l'article non sélectionné est illisible, surtout sur un mobile en plein soleil, il n'y a aucun support de plugins, les raccourcis claviers sont complètement dissociés du contrôle à la souris et il me semble assez lourd quand on charge de nombreux articles.
selfoss
Ça commence bien, le site est beau et les screenshots donnent envie, mais qu'en est-il vraiment ? Déjà, c'est compliqué : l'installation est compliquée, la configuration se fait dans un fichier config.ini, il n'y a pas de démo disponible, et quand on finit par l'installer pour le voir en action, on se rend compte que ce n'est quand même pas très utilisable.
RSS Lounge
Connu pour sa lourdeur, il fait tout (ou presque, il ne fait pas encore le café), on passe.
cartulary
C'est compliqué, le README est paumatoire, alors qu'il n'y a vraiment aucune raison d'expliquer de façon si compliquée une installation somme toute assez basique.
RSS Miner
Le site ne s'affiche pas correctement chez moi, la barre de gauche cachant la moitié de la page et ne se fermant pas, je m'attends au pire et je n'ai pas regardé plus en détails.
News Blur
Il y a des idées, notamment le côté social. Mais c'est compliqué, et hors de portée de beaucoup de monde, car ça tourne sous Django, avec du MongoDB et du PostgreSQL. Je ne suis pas sûr que le côté social soit compatible entre plusieurs instances et utilise un réseau décentralisé pré-existant, qui permettrait de le plugger facilement avec Diaspora ou n'importe quel autre logiciel du genre, et évitant de multiplier les réseaux et les protocoles.
Feed HQ
Inscription obligatoire pour tester, c'est aussi du python + redis + postgresql + elasticsearch, donc on oublie pour Mme Michu.

Que conclure de ce panorama ?

Quoi que je fasse, je reviens vers Leed. De nombreuses fonctionnalités sont annoncées depuis un moment, et j'attends qu'elles voient le jour, mais il reste le plus fonctionnel et celui qui colle le mieux avec mon lecteur RSS idéal, tout en restant loin de la perfection. Le reste est moche, complexe, lent, et même les solutions payantes (mais opensources) ne s'en sortent guère mieux. Je n'utilisais pas Google Reader, mais s'il était dans la tradition des outils Google (simple, fonctionnel et rapide), je n'ai pas (encore ?) trouvé de réelle alternative.

Concernant Leed, la première étape est bien sûr de changer le thème par défaut (Marigolds) pour un meilleur thème. Le plus complet et maintenu actuellement est Greeder de tmos (bien que Hot Beer se défende, même si je n'adhère absolument pas au format webzine). tmos travaille sur un pack Leed + greeder et sur l'intégration de Leed dans Yunohost, qui devrait lui redonner un peu de fraîcheur.

Mais du coup, c'est quoi mon lecteur RSS idéal ?

Rapidité, simplicité, fonctionnalité

Je met à jour mon lecteur RSS toutes les heures, et j'y passe donc quasiment une fois par heure. Je ne veux pas passer dix minutes à chaque fois pour réussir à cliquer sur le bon bouton, ou pour attendre que la page soit chargée.

Il faut donc qu'il soit beau, intuitif (pour ça, Leed + greeder remplit bien ce rôle), rapide et fonctionnel. Le but est aussi de lire des articles, pas de voir défiler des titres, donc il faut que les articles soient affichés en entier (mais personnalisables via une option pour satisfaire tout le monde), sans avoir besoin de cliquer trois fois sur chaque article pour le lire.

Je le regarde de partout, et beaucoup sur mon portable, dans les transports. Or, bien souvent, il n'y a pas de réseau dans les transports, et je ne veux pas d'une énième app quand du HTML5 peut le faire. Du coup, un thème responsive, des actions tactiles (comme Greeder, en plus étendu) et une utilisation du local storage et le tour est joué :)

Toutes ces fonctionnalités (et celles qui vont suivre) peuvent paraître en contradiction avec « être léger, rapide et fonctionnel », mais si le script est suffisamment compartimenté, on peut ne charger que ce qui sera utile à l'affichage et conserver un grand nombre de fonctionnalités avancées, sans alourdir nécessairement le script (sauf dans le cas où tout serait activé en même temps).

Extensibilité et customisation

On ne peut pas faire un logiciel parfait, qui satisfasse tout le monde. Plutôt que d'opter pour le minimalisme et se priver ainsi de fonctions avancées, un système de plugins bien pensé me paraît mieux. Celui de Leed est bien pour ça, même s'il manque un peu de documentation. Idéalement, il faudrait même que les plugins et thèmes existants pour un des lecteurs RSS les plus répandu actuellement soient compatibles (mais là, je rêve je pense :).

Quelques idées de plugins cools en vrac :

  • Recherche : très souvent je lis des articles, puis quelques jours plus tard je réalise que j'aurais du les garder de côté car j'en ai besoin. Sauf qu'à ce moment, je ne sais plus sur quel flux je l'ai lu, et c'est une galère de le retrouver. Un plugin de recherche sur l'agrégateur permet de résoudre ce problème.
  • Une implémentation de rss-bridge pour le côté user-friendly.
  • Des plugins spécifiques par flux, pour afficher les conversations entre shaarli en tant que conversations par exemple.
  • Annotation de texte en direct pour noter rapidement des idées, des corrections de typo etc.

Pour le côté user friendly et l'adoption par Mme Michu, il faudrait aussi une liste de plugins « officiels » (c'est-à-dire respectant les guidelines et donc compatibles) simple, à la wordpress. Il suffirait alors d'envoyer l'archive dans l'interface admin pour l'installer automatiquement.

Idéalement, il faudrait des coding guidelines strictes, qui manquent sur les projets actuels. Notamment sur la façon d'écrire un thème ou sur les balises à utiliser dans un thème, afin de garantir la cohérence de l'interface et la rapidité du script. Leed par exemple, a un dépôt market très hétérogène, et des thèmes qui n'ont pas de base commune rendant très difficile l'implémentation de nouveau code sur plusieurs thèmes. Pire, certains plugins doivent être adaptés pour chaque thème, ce qui est une perte de temps considérable.

Une gestion fine des flux

Une autre fonctionnalité qui me paraît importante est de pouvoir gérer finement les flux, c'est-à-dire pouvoir prioriser, classer, trier et filtrer des flux très facilement.

Un premier point est la gestion des doublons. Très souvent, il arrive d'avoir des articles similaires, sur le même sujet, voire même des articles tout simplement identiques, si certains flux se recoupent. Le premier cas est difficile à trier et à filtrer (même si idéalement ces articles devraient pouvoir être regroupés ensemble), mais le deuxième est très simple à filtrer. Les doublons devraient donc être masqués et gérés comme un seul et même article.

Un autre point important est la présence du multi-utilisateur. Cela permet ainsi de ne charger qu'une seule fois les liens communs à plusieurs comptes, et d'accélerer le rafraîchissement des liens ainsi que d'alléger la charge des serveurs. Je vois deux cas d'utilisation importants : pouvoir avoir une seule instance pour tout une famille, et pouvoir avoir différents comptes par activité (un compte pro et un compte perso par exemple).

D'autres fonctionnalités sympathiques sont proposées par certains lecteurs RSS, notamment la gestion de la priorité des flux, pour prioriser certains flux.

Je pense aussi qu'il y a moyen de faire des trucs très sympas avec les dossiers, qui sont bien trop rigides comme fonctionnement (et que je n'utilise pas personnellement). Sûrement un système de tags, ou un système flexible par mot-clé. Mais je n'ai pas encore d'idées précises à apporter pour cette réflexion. N'hésitez pas à partager les votres :)

Transparence et protection de la vie privée

Un des principaux avantages de s'auto-héberger est d'avoir les contraintes de transparence, de sécurité et de protection de la vie privée qu'on se fixe, au lieu d'être dépendant d'une solution tierce sur ces points.

Un lecteur RSS idéal, et toujours dans l'optique de l'utilisation par le plus grand nombre, devrait :

afficher de manière claire les logs disponibles
on ne devrait jamais devoir aller chercher une information dans un obscur fichier de log écrit dans le répertoire du script, ou pire, dans les logs Apache. Au contraire, ces informations (historique de connexions, historiques de mise à jour, …) devraient être disponibles dans l'interface directement, de façon claire et compréhensible en un clin d'œil.
des statistiques claires
de même, une fonctionnalité absente de nombreux lecteurs RSS et qui me semble pourtant plutôt basique est la possibilité de voir en un clin d'œil quels sont les flux fréquemment mis à jour, quels sont les flux les plus actifs, les moins actifs, etc., ceci afin de pouvoir très facilement trier ses flux et supprimer les flux morts. Il m'est arrivé plusieurs fois d'avoir un flux qui a changé d'adresse, ou qui était momentanément indisponible, et de mettre plusieurs jours à m'en rendre compte, faute d'affichage clair comme "attention, le flux XXX n'a pas été mis à jour depuis N jours, alors qu'il avait une fréquence habituelle de M articles / jour"
régler finement les permissions
S'auto-héberger, c'est aussi pouvoir régler finement les fonctions avancées de ses logiciels. J'utilise intensivement la vue anonyme de Leed, pour ne pas avoir à me connecter à chaque visite, et car je trouve ça pratique de pouvoir voir les flux RSS que les autres suivent, on découvre bien souvent de nouveaux flux top comme ça. Mais sur la plupart des lecteurs actuels, soit tout est public, soit tout est privé. Or je ne veux pas forcément que tous mes flux soit publics. En particulier, certains flux liés à des services que j'utilise (mon Owncloud, par exemple) ne devraient pas être publics.
être compatible avec les autres outils libres à disposition
Enfin, même si je souhaite beaucoup de fonctions dans mon lecteur RSS, je ne veux pas qu'il devient un monstre polycéphal qui fait tout. Le libre a cela de merveilleux qu'il existe une infinité de petits outils qui font une seule petite tâche, mais la font très bien. Pourquoi implémenter aussi une gestion des favoris, quand Owncloud le propose, quand shaarli marche du tonerre et est de surcroît très simple à installer, etc. Il faut donc au contraire prévoir d'être compatible avec ces autres outils, pour que le libre soit cohérent. En particulier, owncloud propose un flux RSS accessible après authentification (POST) des "activités" sur le compte. Pratique pour suivre des dossiers partagés. Mais très peu de (si ce n'est aucun) lecteur RSS disponible ne gère cette authentification =(.
promouvoir la vie privée de l'utilisateur
En utilisant son propre lecteur RSS auto-hébergé, on a un contrôle total sur nos flux, et on ne divulgue pas d'informations non contrôlées à un tiers (typiquement l'hébergeur du lecteur RSS, qui pourra alors nous cibler plus finement). J'aimerais pouvoir retrouver ça dans mon lecteur avec un filtrage des liens feedburner par défaut, pour supprimer ces redirections et les remplacer par des liens directs, ainsi qu'un filtrage des publicités dans les flux, un peu à la manière des plugins urlclean et adblock pour Leed. Il pourrait aussi cacher le referer lors de l'ouverture d'un lien externe, etc. Il y a énormément de possibilités de ce côté.

Toujours garder l'ergonomie en tête

L'ergonomie est sûrement un des points faibles des lecteurs RSS disponibles actuellement (et du logiciel libre ?). Elle est bien souvent négligée, et cela prive bon nombre d'utilisateurs d'utiliser les scripts en question.

Pourtant, il y a moyen de faire beaucoup de choses, notamment en usant (abusant ?) de JavaScript et des fonctionnalités récentes (transitions CSS, HTML5 etc). Du drag&drop s'implémente facilement, et facilite grandement l'utilisation pour beaucoup d'utilisateurs. Décrémenter un compteur d'éléments non lus en JavaScript chaque fois qu'on marque un élément comme lu prend 3 lignes de JavaScript et pourtant cela n'a été implémenté que récemment dans Greeder et dans le thème par défaut de Leed.

De plus, j'ai besoin d'une application web pour ne pas dépendre de l'ordinateur (ou du téléphone) que j'utilise. Que je sois sur mon téléphone, mon ordinateur ou n'importe quel autre périphérique, je retrouve mes news dans le même état, sans synchronisation compliquée, et sans développer un logiciel différent par périphérique. Le web est vraiment magique pour ça. Mais ce n'est pas pour autant que je ne veux pas que cette webapp se rapproche le plus possible d'une application native (qui sont bien souvent des wrappers autour d'une interface web, sur mobile, de toutes façons). Ainsi, sur mon portable, je veux retrouver des actions tactiles, un stockage en local storage car je risque d'être déconnecté sans raison, et une interface utilisable pleinement sans jouer avec le zoom. Et sur mon ordinateur, je veux pouvoir bénéficier d'une navigation au clavier, avec des raccourcis claviers, et de fonctionnalités avancées telles que le rafraîchissment régulier ou la notification, afin de se rapprocher le plus possible d'une application (et peut être un jour tourner dans sa propre instance du navigateur, pour ressembler vraiment à une application ?).

Côté interface, celle-ci doit faciliter la lecture en mettant l'accent sur le contenu et les actions importantes. Il y a aussi beaucoup de boutons qui ont une fonction peu claire dans les scripts que j'ai pu voir : double négation dans les questions qui nous fait répondre « oui » quand on voulait dire « non », pas de rappel du nom du dossier quand on veut marquer tout un dossier comme lu (ce qui nous fait nous demander si on a bien cliqué sur le bon bouton)… D'autre part, quand je qualifiais les interfaces de « moches » au début de cet article, c'était bien souvent que l'interface était peu claire / paumatoire / clicodrôme.

La mode est au scroll infini. C'est bien pratique quand on a une connexion permanente, mais dès que la connexion coupe, qu'on recharge la page, et qu'on se retrouve tout en haut, c'est nettement moins drôle. Du coup, vive la pagination, en gardant une option pour le scroll infini, pour ceux qui l'aiment particulièrement. Par contre, si le local storage est très largement utilisé, le scroll infini peut s'envisager, car la perte de connexion ne bloquera pas la page.

Enfin, un dernier point essentiel à mon avis est la possibilité de se connecter automatiquement et d'avoir un bookmarklet efficace pour ajouter des flux (idéalement, une intégration directe avec le module d'abonnement de Firefox :). Leed a un bon bookmarklet mais la connexion automatique n'est arrivée que récemment. Et attention sur ce point, Shaarli a une connexion automatique erratique, qui a tendance à ne pas passer chez certains hébergeurs.

ParaîtreÊtre sérieux

Trop de scripts de ce genre ont aussi des traductions approximatives, monkey patchée ou bourrées de fautes. L'inernationalisation est importante de nos jours et ne doit pas être négligée, surtout qu'elle est désormais facilitée par les outils disponibles et qu'elle n'est pas si problématique si pensée depuis le début. Faire un test sur les nombres à afficher pour afficher l'accord si besoin n'est pas très long, et il est possible de faire une fonction à appeler pour le faire à chaque fois. Ce n'est pas grand chose, mais c'est plus propre, plus beau et plus tentant. Une bonne traduction, une bonne licence, un code en anglais et des coding guidelines motiveront plus les gens pour écrire du code et faire des contributions.

Il faut aussi avoir une sortie régulière de versions, quitte à sortir des versions rapprochées. Si toutes les nouvelles fonctions sont regroupées dans une branche dev et regroupées dans une version stable une fois par an, Mme Michu ne verra qu'une version par an, et se dira donc que le développement est lent, même si chaque version apporte énormément de nouveautés. Au contraire, un dépôt avec des commits réguliers est plus attirant car on se dit que le logiciel vit, qu'il est suivi et qu'on n'aura donc pas à attendre longtemps si on rencontre un problème avec. Personnellement, si je rencontre un problème bloquant avec un logiciel et que celui-ci n'est pas résolu rapidement (en quelques semaines tout au plus), que je le veuile ou non, j'oublie l'existence de ce logiciel, je trouve des alternatives, et je retombe dessus par hasard quelques mois plus tard.

De même, on ne peut pas tout développer, et on ne peut pas tout réinventer. Du coup, il devient important de virer les fonctionnalités inutiles, ou qui font doublon avec d'autres programmes, pour ne pas réinventer la roue et se consacrer sur les points essentiels pour le script.

Et tout cela… pour tous

Comme j'ai déjà insisté pas mal dessus, je reprendrais juste brièvement quelques points dans cette partie. Mais pour rester dans l'érgonomique et le beau, un tel script devrait être facile à installer, à configurer et à utiliser, par tous.

Ceci passe par une interface user friendly, utilisant pleinement les fonctionnalités offertes par les navigateurs aujourd'hui (drag&drop, AJAX, …). Ceci passe aussi par l'internationalisation, la présence d'une vraie liste d'extensions, facilement utilisable, une doc claire et à jour et un fonctionnement identique (dans la mesure du possible) sur la plupart des hébergements disponibles.

Du côté de la licence, un tel lecteur RSS devrait être sous une licence libre (dans le sens de logiciel libre), ce qui n'est malheureusement pas le cas de Leed aujourd'hui (sous licence CC-BY-NC-SA), qui a d'ailleurs une licence ambiguë, déconseilleé pour les codes sources (voir ici ou ici) et complexe comme le montre cet article chez Framasoft, un comble pour une licence qui se veut simple et intuitive. :)

Enfin, un des principaux points est sûrement de pouvoir mettre à jour les flux facilement, sans y penser et sans intervention. Actuellement, la plupart des lecteurs nécessitent une intervention de l'utilisateur pour ajouter une crontask. C'est compliqué, source de problèmes, d'erreurs en recopiant etc, et ça complique l'installation pour pas mal de monde. Il y a sûrement moyen de rendre cela plus facile aussi, en tout cas ça serait top si c'était le cas. Owncloud par exemple propose de lancer les tâches par AJAX, webcron ou cron, sans configuration de la part de l'utilisateur.

Conclusion

Aucun lecteur RSS ne me satisfait pleinement, mais Leed me paraît le moins imparfait à l'heure actuelle. En prenant des briques à gauche, à droite, on réunit la plupart des fonctions qui me paraissent importantes, mais je pense qu'il y a encore moyen de faire beaucoup pour s'affranchir des modèles classiques et établis de lecteurs RSS et proposer quelque chose d'innovant, misant sur l'ergonomie et s'adressant au plus grand nombre.

Je vais essayer de mettre ça en pratique, en gardant en tête les points que je juge le plus important : facilité d'utilisation, ergonomie, beau et performant. Je ferai sûrement quelques articles sur des points spécifiques que je croiserai. Si vous me lisez et que vous avez un hébergement mutualisé, n'hésitez pas à me donner des infos sur votre hébergement PHP (version de PHP, modules disponibles qui sont trouvables dans le phpinfo notamment) car je ne sais pas exactement quelles sont les installations typiques de PHP sur mutualisé.

Enfin, beaucoup de fonctionnalités seraient implémentées très facilement en utilisant les technos à la mode, nodejs ou les solutions à base de python par exemple. Mais cela oblige à se priver du côté « facilement installable par tous » car ces solutions ne sont pas disponibles sur la plupart des hébergeurs mutualisés. Ça semble aussi être un des problèmes de Diaspora* par exemple, car j'entends régulièrement qu'installer son pod est compliqué, notamment car Diaspora* utilise Ruby, C'est vrai, et si c'est pour utiliser un pod public, proposé par la communauté, beaucoup d'utilisateurs ne voient pas de réelles différences par rapport à Facebook,

, ,

 

Élysée.fr… accessibilité et cloud souverain

3 min read

Vous avez sûrement déjà vu un site officiel sur l'IVG utiliser Google Analytics, ce qui n'est pas sans poser quelques problèmes d'anonymat et de confidentialité, un cloud souverain mais vous n'avez sûrement pas encore vu le site de l'Élysée (en tout cas, moi je ne l'avais jamais vu il y a encore quelques jours) !

Mais hier, je suis tombé sur cet article sur le blog webatou qui reportait des popins sur le site de l'Élysée, comportement assez étonnant pour un site officiel, qui vante son accessibilité (mais non, il n'y a bien sûr aucun popin sur cette page…), qui fait appel à une société (dont on n'ose même pas imaginer la facture) pour améliorer son accessibilité. Ok, elle n'était pas parfaite, mais c'était déjà ça.

Mais alors, que leur a-t-il pris de mettre un énorme popin pour les suivre sur Facebook (sérieusement, la présidence est tellement en manque de reconnaissance, qu'il lui faut des likes sur Facebook ?). Pas de problèmes, je clos le popin. Prochain chargement, la même chose pour Twitter ! Je ferme encore, prochain rechargement, la même chose pour la newsletter. Je suis assez grand pour savoir où je veux vous suivre tout seul, pas besoin de 3 popins !

Du coup, je me suis penché un peu plus sur le site, et je suis juste consterné… On passera sur l'enveloppe en haut de page qui n'a rien à voir avec un quelconque contact, mais permet juste de s'abonner à la newsletter, on passera sur les mêmes pages qui sont liées à N endroits différents sur le site, avec un texte différent à chaque fois, idéal pour perdre le visiteur (mais bon, c'est une spécialité des services publics apparemment)… Non, ce qui m'a inquiété, c'est l'origine du petit script JavaScript responsable du popin.

Pas de problèmes, on recharge la page en activant la console de Firefox, et on découvre qu'il n'y a pas moins de 15 scripts différents chargés (totalisant un poids voisin de 900ko (oui oui, 900ko soit trois fois plus que l'image la plus lourde de la page, mais ), ce qui est finalement dans la moyenne des pages webs actuelles avec leur tendance à cracher du JavaScript à la pelle) dont un seul hébergé sur le serveur de l'élysée.

Oui oui, vous avez bien lu, sur le site de l'Élysée, il y a 14 scripts (soit 93% des scripts) qui viennent d'un serveur externe (Facebook, google API, Twitter, Typekit et readspeaker). Et je ne parle que des javascripts, pas des images et des CSS (qui finalement sont presque tous chez l'Élysée pour le coup). Ça veut donc dire qu'au moins 4 grandes entreprises américaines peuvent inclure un peu ce qu'elles veulent sur la page de l'Élysée. Joli !

Enfin, on notera que le seul contact que j'ai pu trouver pour l'équipe responsable du site de l'Élysée était une adresse postale à l'Élysée, pratique à l'heure où envoyer un e-mail n'a jamais été aussi simple et rapide.

P.S. (disclaimer) : Pour tous ceux qui chercheront à relever tous les problèmes d'accessibilité sur mon blog, je sais qu'il est loin d'être parfait, et il faudra que je m'en occupe quand j'aurai 5 minutes. Sauf que dans un cas on parle d'un blog personnel, n'ayant aucune prétention particulière, et dans l'autre cas on parle d'un site institutionnel qui se prétend modèle d'accessibilité…

 

Timeline.js, une lib pour tracer des graphes en JavaScript

3 min read

Pour un projet (dont je reparlerai sûrement bientôt, au passage), j'ai eu besoin de tracer des graphes en JavaScript. Le moyen le plus simple, sachant qu'en plus j'avais besoin d'un peu d'interactivité, était d'utiliser du SVG et de le générer directement en JavaScript.

J'ai donc pensé utiliser une bibliothèque déjà écrite… et c'est là que le bât blesse… On trouve de très bonnes bibliothèques, pour faire de très beaux graphes avec des animations et tout et tout, mais rien de léger, simple et fonctionnel. Je voulais juste tracer des graphes en SVG (potentiellement plusieurs superposés) et avoir des actions personnalisables au clic sur un point. Pas d'animations, ça ne sert à rien, pas de tracés de multiples objets différents en SVG, juste des graphes… Alors, pourquoi charger 30ko de jQuery plus minimum 10ko de Javascript supplémentaires (ça c'était uniquement pour la plus légère, la moyenne était plutôt autour de 70ko supplémentaires) juste pour faire ça ?!?

Du coup, j'ai écrit une petite bibliothèque JavaScript KISS pour tracer des graphes en SVG. Vous pouvez mettre autant de graphes que vous voulez, spécifier le remplissage souhaité, le type de tracé souhaité, et comme c'est du SVG, c'est très simple de binder des événements JavaScript sur vos points (la bibliothèque supporte du clic par défaut, et il y a une petite animation au survol avec une légende). Le tout pour 23ko non compressé (soit moins que jQuery seule, soit dit en passant), et 15ko une fois minifiée, sans aucune dépendance externe. Ça devrait marcher sans problème sur tous les navigateurs décents (pas de fallback compliqué sur du canvas ou autre implémenté par contre) et on peut même descendre sous les 10ko en obfuscant un peu le code.

Voilà, je ne sais pas si ça servira à quelqu'un, mais on sait jamais. Du coup, si ça vous intéresse, ça se récupère ici sur Github et il y a mêmes quelques exemples de démos ici. Le code n'est sûrement pas parfait, mais ça devrait être fonctionnel (et n'hésitez pas à signaler les issues que vous rencontrez). Comme toujours, c'est sous licence SODAWARE : en gros, vous en faites ce que vous voulez, comme vous voulez, mais c'est quand même cool de dire où vous l'avez trouvé (et c'est quand même vraiment pas cool de s'approprier le travail des autres…) et si vous trouvez ma petite bibliothèque utile / fun / cool / whatever et que par hasard on se croise (ou non), vous pouvez me payer un soda (ou plus) :). Et surtout, n'hésitez pas à faire des pull requests ou à me faire signe si vous vous en servez, que je vois tout ce qu'on peut faire avec :)

 

Détecter l'appui sur "é" en javascript

3 min read

Pour les besoins d'un plugin pour le thème greeder de Leed (gestion des raccourcis claviers), je devais détecter l'appui sur n'importe quelle touche du clavier en javascript. Pour ce faire, a priori, ce n'est pas très dur, il suffit de surveiller l'événement onkeydown et de récupérer le keycode correspondant. Cette méthode fonctionne sans problèmes sur des claviers azerty / qwerty (tout du moins pour ce que je voulais faire) mais pose de graves problèmes sur des dispositions exotiques type Bépo (ty tmos de me l'avoir signalé :). En effet, ces dispositions possèdent de nombreuses touches particulières, qui ne sont pas traitées par la méthode précédente. Ainsi, il était impossible d'assigner un raccourci à la touche "é" ou "É" par la méthode précédente (pas de problème sur un clavier azerty/qwerty car cette touche est alors détectée comme "2").

Après quelques recherches, j'ai découvert qu'il existait déjà deux moyens de savoir quelle touche était pressée : which et keycode. Dans la majorité des cas, ils fournissent le même résultat, sauf dans le cas qu'on veut justement traiter. Je n'ai pas approfondi la question mais il semble que which est plus général, et d'après mes tests, il fonctionne sur toutes les touches utiles d'un clavier azerty/qwerty/bépo. Attention en revanche, les codes renvoyés par which peuvent différer des keycode pour les caractères exotiques.

Mais cela ne suffisait pas. J'avais beau utiliser which qui devait me retourner un certain code de touche, je n'avais rien. Après quelques tests, je me suis alors aperçu qu'il n'y avait purement et simplement aucun événement lancé lors de l'appui sur la touche fautive...

En effet, il existe encore une fois plusieurs événements disponibles sur l'appui d'une touche. Le plus simple, et le plus naturellement adapté pour détecter des raccourcis claviers est onkeydown, qui n'est émis qu'une seule fois, lors de l'appui d'une touche. Mais cet événement n'est pas déclenché lors de l'appui sur certains caractères spéciaux (dont é). La solution est alors de faire un code légèrement plus lourd en utilisant onkeypress en remplacement. onkeypress est déclenché tant que la touche est appuyée (ce qui veut dire de potentiels événements multiples, contrairement à onkeydown) mais a le mérite de fonctionner avec toutes les touches des dispositions azerty/qwerty/bépo.

En résumé, pour détecter un appui sur n'importe quelle touche du clavier, il faut utiliser l'événement onkeypress et détecter le code de la touche avec which. Cela fonctionnera, en échange d'une légère baisse de performances du script. Dommage que ceci n'ait pas été harmonisé ou simplifié un minimum...

,