Python-ZMarkdown

La moteur markdown de Zds

a marqué ce sujet comme résolu.

Une version JS à un gros avantage cependant, on peut utiliser le même pour faire du wysiwym.

Si il y a des motivés, je pense que c’est jouable. Il faut prendre un parseur existants qui a une ast et dans l’idéal qui est modulable. Désactiver certaines fonctionnalités (exemple typique : le HTML dans le markdown) puis rajouter nos extensions. Clairement la plus compliquée c’est les tableaux mais je pense qu’en regardant le code existant, on peut facilement le porter (je me ferai si besoin). Le reste des extensions sont normalement facile. Une grosse partie des tests sont sous forme de couple me/HTML qui vont être facile à porter. Il y en a certains qui sont en forme de test unitaire mais c’est une minorité.

Le seul défaut que je vois avec un parseur markdown est de ne pas permettre ce qu’on permet actuellement pour le ping : fournir une fonction qui dit si le pseudo est valide ou non. Il faudrait passer par une requête.

Il faut prendre un parseur existants qui a une ast et dans l’idéal qui est modulable.

Kje

Yep, on a tout ça. Je vais pousser un peu le PoC que j’ai commencé hier, ces soirs et ce week-end ça devrait le faire.

L’important c’est qu’on ait un truc maintenable, pas que ce soit Python. Là on a des super bases avec remark et ses plugins, et on est plus nombreux a avoir un peu d’expérience à visiter des AST qu’à avoir touché python-zmarkdown. Je pense que c’est jouable.

Pour le ping, je m’inquiète pas, plusieurs solutions possibles.

+0 -0

On va encore dire que je suis là pour râler pour rien, mais la proportion de développeurs connaissant le javascript (et node, à priori) parmi les contributeurs est très très faible. On me répondra que c’est pas parce que le parseur actuel est en python que plus de personnes y contribuent, mais je tiens quand même à noter ça quelque part. Si le plan, c’est que ce sois vhf qui bosse dessus seul à la place de Kje qui bosse dessus seul, je sais pas ce qu’on aura gagné dans l’histoire (à part un AST).

Avant que ce sois mal interprété, la même remarque pourrait être faite pour n’importe quel langage (au hasard, C et Java pour lequels les parseurs existent aussi). De plus, je ne doute aucunement de la motivation de vhf, mais quand même.

Je vais me permettre un argument audacieux : et si les contributeurs de notre projet python étaient des développeurs python parce que le projet est en python ? Et si les développeurs qui ne font pas de python ne contribuaient pas à ZdS parce qu’ils devraient faire du python ?

Je ne vais pas dire que c’est vraiment la mauvaise foi habituelle, mais quand même.

+5 -0

En fait vu que je suis le seul a toucher à Python-ZMarkdown, un parseur fiable dans un langage où il y a au moins un mainteneur possible, où on peut récupérer une AST +, si c’est fait en js, une solution utilisable a raison en serveur et front, ce sera toujours mieux que actuellement.

Qu’on se comprenne bien, je préfère 1000x python à js. Mais comme SpaceFox c’est un des composant où ça a tout son sens : on pourrait avoir le même parseur des deux coté (front et back) et donc, a minima, l’utiliser pour faire l’aperçu sur le client sans risque d’avoir des rendus qui correspondent pas.

Perso je suis pragmatique. Aujourd’hui pour faire évoluer le markdown il nous faut une ast. L’ajouter au parseur existant est long et couteux. Il est pas plus long et couteux d’en prendre un autre et d’y rajouter nos extensions. Du coup on peut s’affranchir du langage si ça se justifie (et justement pour ce composant il y a de sérieux arguments de vouloir le faire en JS). Enfin, niveau dev, si on a plus d’un dev js qui connait le dev du parseur, on en a autant qu’en python. Donc si un dev fait un portage de nos extensions, on a autant de dev (et ça sans te dire que même moi je pourrais le maintenir autant que ce que j’en fait actuellement sur la version python, j’ai juste pas le courage, ni le temps, de faire le dev js, j’en fais trop au boulot pour faire un gros dev le soir).

Donc selon moi, si quelqu’un ce sent de le faire, et qu’il le fait, on saura au pire dans la même situation qu’actuellement.

+3 -0

@Kje j’ai repris toutes tes fixtures et les ai mis dans une suite de tests ici : https://github.com/vhf/zmarkdown/tree/master/test/fixtures

Par contre je ne connais pas les fichiers .cfg qui les accompagne. On va éviter de perdre du temps à essayer de faire passer des tests qui ne passaient déjà pas avant, du coup si tu peux me résumer comment marchent ces fichiers ou me pointer vers leur doc, volontiers.

@Drulac, @ toute personne intéressée, voici la doc pour écrire des plugins : https://github.com/wooorm/remark/blob/master/doc/plugins.md

Ces plugins s’ajoutent par .use(monPlugin) ici : https://github.com/vhf/zmarkdown/blob/e89942339bbc79d2aa315b97cddb7ea87e1c0234/index.js#L8 et jouer à console.log sur l’AST ou les transformations est également jouable dans ce même fichier.

Le but est que les tests passent. Le moyen d’atteindre le but est d’écrire des plugins.

npm run test

Notez que le but est principalement le même rendu et les mêmes fonctionnalités, pas le même HTML à la goutte près. Ça ne pose aucun problème vu qu’on stock le HTML et le Markdown. Un bon exemple de ceci : Si actuellement on fait & -> & et que le nouveau rendu fait & -> &, on s’en fiche.

+1 -0

faudra que je me reseigne sur comment fonctionne un ast car là je pige rien à leur système de plugin et le code qu’ils produisent en exemple m’est totalement obscure. Mais bon ça peut être sympa.

artragis

Je ne peux que t’encourager. C’est un concept très répandu. Comme presque tout en computer science c’est pas un passage obligé, mais ça permet d’étendre son horizon.

En très gros, on parse un fichier pour en créer un arbre d’après certaines règles. On peut ensuite appliquer des transformations à cet arbre, par exemple en le parcourant et en appliquant une fonction sur ses noeuds. On peut ensuite faire une projection de cet arbre, par exemple en sortant le contenu seulement de certains noeuds.

C’est ce qui est généralement utilisé par les interpréteurs et compilateurs de tous types. C’est ce qui est utilisé pour de l’analyse statique également. C’est utilisé pour les "code transform". Etc. :)

Voici plus de doc sur les plugins en question : https://github.com/unifiedjs/unified#plugin

+1 -0

malheureusement ces généralités ne m’ont rien appris :(

et je ne bite toujours rien à leur code ^^ ne serait-ce que celui-là qui est pour moi totalement abscons :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
function move(options) {
  var expected = (options || {}).extname;

  if (!expected) {
    throw new Error('Missing `extname` in options');
  }

  return transformer;

  function transformer(tree, file) {
    if (file.extname && file.extname !== expected) {
      file.extname = expected;
    }
  }
}
  • la fonction est déclarée après le return
  • à quoi sert de déclarer une fonction de cette manière sans être dans le scope global?
  • le code prend un "tree" mais ne l’utilise pas, donc je vois pas l’intérêt.
  • return transformer retourne une fonction
  • function () {} est hoisté, donc pas besoin de la déclarer avant de l’utiliser
  • transformer est le plugin : il sera toujours appelé de la même manière, ici avec tree et file. Si je te dis "donne-moi une fonction que j’appelle en faisant f(foo, bar)", et tu te fiches de foo, tu peux pas pour autant me donner une fonction qui ne prend que bar
  • transformer est une closure, l’intérêt est de bénéficier du contexte parent, ça en fait un truc configurable
  • Peut-être que si tu considères simplement que move est un movePluginFactory qui prend config en argument et retourne un movePlugin ainsi configuré tu comprends mieux ?
+0 -0

Disons que ton dernier point est la seule chose que je comprenais (puisque justement le principe des plugin c’est que soit on est un transformer, soit un attacher.

Pour le second point, je ne connais pas le mot "hoister" mais je pense le comprendre. Ici c’est juste que je trouve que déclarer une fonction après avoir retourné une référence à icelle.

Pour ce qui concerne les closures, c’est sûrement le seul concept du truc que je maîtrise vraiment.

Disons que ton dernier point est la seule chose que je comprenais (puisque justement le principe des plugin c’est que soit on est un transformer, soit un attacher.

artragis

Du coup tu comprends tout à fait pourquoi transformer n’est pas dans le scope global. :)

+0 -0

Pourquoi il n’est pas dans le scope global, oui, c’est pas ça mon problème, c’est quej e pige pas l’intérêt de ce plugin. Pour illustrer un transformer, faire un truc qui ne travaille pas sur l’arbre c’est étrange.

Bref, je regarderai vos code et je comprendrais certaineemnt mieux, le code de zds est un des codes plus plus clean que j’ai vu.

En Speed, pour les cfg de mémoire (ça vient du dépôt d’origine) ça specifit les options du parseur pour chaque fichier de test du dossier (+ un default pour ceux pas listé).

Certains tests sont spécifiquement désactivé ainsi.

Regarde ceux spécifique aux tests de zds : ça dit quelle extensions activer et le cas échéant definit des paramètres (par ex les smileys)

Bon, j’ai un peu joué avec remark et écrit un premier plugin pour le prendre en main. C’est plutôt bien foutu et le projet que j’ai mis en place est pratique pour développer.

C’est ici : https://github.com/zestedesavoir/zmarkdown

Je vais ouvrir des issues pour documenter le travail à faire. Il y a certains comportement dans Python-ZMarkdown qui m’échappent un peu, j’aimerais bien revenir plus proche de la spec. Exemple : Mettre un bloc de code, par indentation, dans une liste.

En markdown, c’est :

1
2
3
4
5
* list item

      indented code

`

En ZMarkdown (louche), c’est :

1
2
3
4
5
* list item

        indented code

`

(oh btw regardez, il y a un bug ci-dessus)

Il y a aussi le "hard wrap" avec lequel je suis un peu en désaccord.

+0 -0

Oui, pardon, c’est dans le projet python-zmarkdown et ça vient du markdown originel :

1
2
3
4
5
6
7
8
In Markdown 1.0.0 and earlier. Version
8. This line turns into a list item.
Because a hard-wrapped line in the
middle of a paragraph looked like a
list item.

Here's one with a bullet.
* criminey.

devrait donner :

1
2
3
4
5
6
7
<p>In Markdown 1.0.0 and earlier. Version
8. This line turns into a list item.
Because a hard-wrapped line in the
middle of a paragraph looked like a
list item.</p>
<p>Here's one with a bullet.
* criminey.</p>

ou

1
2
3
4
5
6
7
<p>In Markdown 1.0.0 and earlier. Version
8. This line turns into a list item.
Because a hard-wrapped line in the
middle of a paragraph looked like a
list item.</p>
<p>Here's one with a bullet.</p>
<ul><li>criminey.</li></ul>

(Je penche pour cette dernière, comme dans github/commonmark.)

J’ai le sentiment que le test a été mal écrit et que le python-zmarkdown s’est adapté à cette erreur de test. Ici, le problème est la ligne 2 du markdown. Elle ne doit PAS être interprétée comme une liste 8. blah.

+0 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte