27 votes

Aurélia : vérification de l'intégrité des modèles html ?

J'ai récemment demandé pourquoi les éléments de fermeture automatique ne fonctionnent pas dans le système de modélisation d'Aurélia ; et c'était parce que les éléments qui se ferment automatiquement sont des html invalides.

Pourtant, aujourd'hui, j'ai à nouveau fait la même erreur (avec des widgets cette fois) et je me suis demandé pourquoi le contenu était absent.

Question : Existe-t-il un moyen de nettoyer le template html d'Aurelia dans une tâche gulp ?

J'ai essayé d'utiliser :

  • gulp-htmlhint : impossible d'obtenir une erreur sur les éléments auto-fermés
  • gulp-htmllint : je n'ai pas pu le configurer ; avec les paramètres par défaut, il explose avec des erreurs.
  • gulp-html5-lint : ne semble pas configurable et déteste les attributs d'Aurélia.

7voto

Meirion Hughes Points 1855

Nous pouvons résoudre le problème de la recherche et du signalement des éléments à fermeture automatique avec parse5 . Il possède une classe SAXParser qui devrait être assez robuste (parse5 est conforme aux normes html5). Le parseur lève un événement, lorsqu'il trouve une balise start-tags, qui contient un booléen indiquant si la balise trouvée se ferme d'elle-même.

var parser = new SAXParser();

parser.on("startTag", (name, attrs, selfClosing)=>{
    if(selfClosing){ 
        //check if name is void, if not report error       
    }
});

parser.push(html);

Pour utiliser cette fonctionnalité, j'ai mis en place un projet qui peut être utilisé afin d'aider à assainir le html en utilisant l'approche ci-dessus. L'outil lint développé est capable d'exécuter une sélection de règles, de collecter toutes les erreurs et de les retourner sous forme de promesse. Cela peut ensuite être signalé à l'utilisateur.

Vanilla Html/Templates

modèle-lint constitue la base du jeu d'outils. Il comprend le Linter, et quelques règles de base :

  • SelfClose - veiller à ce que les éléments non vides ne se ferment pas d'eux-mêmes
  • Parser - renvoie des erreurs pour les éléments non fermés ou mal assortis, tels qu'ils sont capturés pendant l'analyse syntaxique.

gulp-template-lint est le wrapper gulp pour template-lint et peut être utilisé comme suit :

var gulp = require('gulp');
var linter = require('gulp-template-lint');

gulp.task('build-html', function () {
    return gulp.src(['source/**/*.html'])
        .pipe(linter())
        .pipe(gulp.dest('output'));
});

Exemple

Étant donné le html suivant :

<template>
  <custom-element/> 
  <svg>
    <rect/>
  </svg>
  <div>
    <div>
    </div>
</template>

produit :

enter image description here

Remarque : le système de fermeture automatique <rect/> ne produit pas d'erreur. Les éléments svg contiennent du xml et les Règles peuvent faire la différence en fonction de la portée.

Modèles Aurélia

J'ai d'abord fait aurelia-template-lint mais nous avons décidé de séparer les composants réutilisables (en dehors d'aurelia) en modèle-lint . Bien que les deux soient actuellement séparés, je vais avoir le aurelia-template-lint s'étendre sur modèle-lint en temps voulu. Il existe actuellement quelques règles de validation du concept :

  • SelfClose - veiller à ce que les éléments non vides ne se ferment pas d'eux-mêmes
  • Parser - renvoie des erreurs pour les éléments non fermés ou mal assortis, tels qu'ils sont capturés pendant l'analyse syntaxique.
  • Modèle - s'assurer que Root est un élément de modèle, et qu'il n'y a pas plus d'un élément de modèle présent
  • RouterView - ne pas permettre à l'élément router-view de contenir des éléments de contenu
  • Exiger - s'assurer que les éléments requis ont un attribut "de".

il existe un wrapper gulp qui peut être installé via :

npm install gulp-aurelia-template-lint

et utilisé dans une construction gulp :

var linter = require('gulp-aurelia-template-lint');

gulp.task('lint-template-html', function () {
    return gulp.src('**/*.html')
        .pipe(linter())
        .pipe(gulp.dest('output'));
});

cela utilisera le jeu de règles par défaut.

Exemple

un test simple avec le modèle aurelia mal formé suivant :

<link/>
<template bindable="items">
<require from="foo"/>
<require frm="foo"/>

<br/>
<div></div>

<router-view>
  <div/>
</router-view>

</template>
<template>
</template>

sorties :

enter image description here

Améliorations

il y a beaucoup d'améliorations à apporter ; par exemple, il y a quelques façons de définir des modèles vanille sans l'option <template> étiquette. Il existe également un certain nombre d'attributs spécifiques introduits par Aurelia qui pourraient être assainis.

3voto

Meirion Hughes Points 1855

Etant donné que personne n'a encore répondu, je vous présente la "Mieux que rien (peut-être)"™ solution.

var gulp = require('gulp');
var gutil = require('gulp-util');

var voidTags = [
    'area', 'base', 'br', 'col', 'embed', 'hr', 
    'img', 'input', 'keygen', 'link', 'meta', 
    'param', 'source', 'track', 'wbr'];

var checkSelfClose = function () {
  function sanitize(file, cb) { 

    var dirty = String(file.contents);

    var matches = dirty.match(/(?:\<[\/\\\-\"\'!() a-z=.]+\/\>)/g);

    var customTags = [];

    if(matches && matches.length > 0)
    {       
        matches.forEach((match)=>{
            var tag = match.match(/[a-z\-]+/)[0];

            if(voidTags.indexOf(tag) < 0)
                customTags.push(tag);   
        });                   
    };

    if(customTags.length > 0)
        gutil.log('WARNING', 'found ' + customTags.length + " non-void self-closed tags in", 
        file.path.substring(file.cwd.length, file.path.Length),
        "tags:", customTags
        );

    cb(null, file);
  }
  return require('event-stream').map(sanitize);
}

gulp.task('build-html', function () {
    return gulp.src('source/**/*.html')
    .pipe(checkSelfClose())
    .pipe(gulp.dest('output'));
});

testé avec :

<template bindable="items">
  <require from="./menu-bar.css" />

  <custom-element/>  
  <custom-element click.delegate="subitem.execute()" repeat.for="item of items" /> 
  <custom-element-moo></custom-element-moo>

  <br>
  <br/>

  <div id="blahblah"/>  

  <button class="dropbtn"/>
</template>

sortie gulp :

enter image description here

[Mise à jour]

Je laisse ceci ici car il s'agit d'un moyen rapide, sale et sans dépendance de vérifier les balises auto-fermées ; cela répond à la question et peut être utile.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X