Aurelia:完整性检查模板 html?

Aurelia: sanity check template html?

我最近问为什么 在 Aurelia 的模板系统中;这是因为自闭元素无效 html。

然而,今天我又犯了同样的错误(这次是小部件),我一直在摸不着头脑,为什么内容丢失了。

问题:在gulp任务中是否可以清理Aurelia模板html?

我试过使用:

鉴于还没有人回答;我提出 "Better than nothing (maybe)"™ 解决方案。

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'));
});

测试:

<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>

gulp 输出:

[更新]

将其留在这里是因为它是一种快速、肮脏且无依赖性的检查自关闭标签的方法;确实回答了这个问题,可能会有用。

我们可以用 parse5 解决查找和报告 self-closing 元素的问题。它有一个应该非常健壮的 SAXParser class(parse5 符合 html5 标准)。解析器在找到 start-tags 后引发一个事件,该事件包含一个关于找到的标签是否自行关闭的布尔值。

var parser = new SAXParser();

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

parser.push(html);

为了利用此功能,我设置了一个项目,可用于帮助使用上述方法清理 html。开发的 lint 工具能够 运行 一系列规则,收集任何错误并将它们 return 作为 Promise。然后可以将此报告给用户。

原版Html/Templates

template-lint 构成 tool-set 的基础。它由 Linter 和一些基本规则组成:

  • SelfClose - 确保 non-void 元素不会 self-close
  • 解析器 - returns 未闭合或 ill-matched 元素的错误,在解析期间捕获

gulp-template-lint 是 template-lint 的 gulp 包装器,可以像这样使用:

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'));
});

例子

给出以下 html:

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

产生:

注意:self-closed <rect/> 不会产生错误。 svg 元素包含 xml 并且规则可以根据范围进行区分。

Aurelia 模板

我最初制作了 aurelia-template-lint,但决定将可重用(aurelia 之外的)组件拆分为 template-lint。虽然两者目前是分开的,但我会在适当的时候让 aurelia-template-lint 扩展到 template-lint。目前有一些 proof-of-concept 条规则:

  • SelfClose - 确保 non-void 元素不会 self-close
  • 解析器 - returns 未闭合或 ill-matched 元素的错误,在解析期间捕获
  • 模板 - 确保根是一个模板元素,并且存在的模板元素不超过一个
  • RouterView - 不允许 router-view 元素包含内容元素
  • 要求 - 确保要求元素具有 'from' 属性

有一个 gulp 包装器可以通过以下方式安装:

npm install gulp-aurelia-template-lint

并在 gulp 构建中使用:

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

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

这将使用默认的规则集。

例子

使用以下 ill-formed aurelia 模板进行简单测试:

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

<br/>
<div></div>

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

</template>
<template>
</template>

输出:

改进

需要做很多改进;例如,有几种方法可以在不使用 <template> 标签的情况下定义原始模板。 Aurelia 还引入了很多可以清理的特定属性。