Skip to content

Commit

Permalink
Tools: Initial import of check-examples script
Browse files Browse the repository at this point in the history
  • Loading branch information
adam-be committed Oct 24, 2017
1 parent d31a9a5 commit 0547efa
Show file tree
Hide file tree
Showing 4 changed files with 153 additions and 0 deletions.
21 changes: 21 additions & 0 deletions check-examples/.eslintrc.js
@@ -0,0 +1,21 @@
module.exports = {
"extends": "google",
"env": {
"browser": true
},
"parserOptions": {
"ecmaVersion": 2017
},
"parser": "babel-eslint",
"rules": {
"require-jsdoc": "off",
"eol-last": "off",
"comma-dangle": "off",
"no-unused-vars": "off",
"quotes": "off",
"max-len": "off",
},
"plugins": [
"html"
],
};
12 changes: 12 additions & 0 deletions check-examples/README.md
@@ -0,0 +1,12 @@
# Check Examples
A script that extracts the example code snippets from the specification and
runs a code linter on them.

## Install and Run
`$ npm install`
`$ node check.js ../webrtc.html`

## Self Linting
Run the linter on the script itself with the same rules that are used for
specification examples:
`$ npm run linter`
101 changes: 101 additions & 0 deletions check-examples/check.js
@@ -0,0 +1,101 @@
const fs = require('fs');
const {spawn} = require('child_process');
const htmlparser = require('htmlparser2');
const Entities = require('html-entities').XmlEntities;

const entities = new Entities();
let isExampleText = false;
let exampleCounter = 0;
let nonPassingCounter = 0;

const parser = new htmlparser.Parser({
onopentag: (tagName, attributes) => {
if (tagName === 'pre' && 'class' in attributes && attributes.class.includes('example')) {
isExampleText = true;
}
},
ontext: (text) => {
if (isExampleText) {
checkExample(text);
isExampleText = false;
}
},
}, {decodeEntities: false});

function printWithLineNumbers(str) {
let count = 1;
const out = str.replace(/^|\n/g, () => `\n${String(count++).padStart(3, '0')} `);
console.log(out);
}

function checkExample(tagText) {
let text = entities.decode(tagText).trim();
const testName = `Example_${++exampleCounter}`;
const fileExt = text.includes('<script') ? 'html' : 'js';

const check = spawn('node_modules/.bin/eslint', [
'--stdin',
'--stdin-filename',
`${testName}.${fileExt}`, // A filename helps to load plugins
]);

// If the "bare" code contains await statements it needs to be wrapped in an async function
if (fileExt != 'html' && text.includes('await ')) {
text = `async () => {\n${text}\n};`;
}

// ESLint doesn't seem to like anonymous objects
if (text.startsWith('{') && text.endsWith('}')) {
text = `temp = ${text};`;
}

check.stdin.setEncoding('utf-8');
check.stdin.write(text);
check.stdin.end();

function printOutput(data) {
console.log(`=== ${testName} ===`);
printWithLineNumbers(text);
console.log('=== Linter output ===');
console.log(data.toString());
}

check.stdout.on('data', printOutput);
check.stderr.on('data', printOutput);

check.on('close', (code) => {
if (code == 0) {
console.log(`${testName}: Passed`);
} else {
console.error(`${testName}: Linter process exited with code ${code}\n`);
nonPassingCounter++;
}
parser.resume();
});

parser.pause();
}

process.on('exit', () => {
const message = nonPassingCounter == 0 ? 'All examples passed'
: `${nonPassingCounter} of ${exampleCounter} examples did not pass`;
console.log(`\nSummary: ${message}`);
});

const filenameIndex = process.argv[0].includes('node') ? 2 : 1;
if (process.argv.length < filenameIndex + 1) {
console.warn('Missing filename');
process.exit();
}

const filename = process.argv[filenameIndex];
fs.readFile(filename, 'utf8', (err, data) => {
if (err) {
console.error(err.toString());
return;
}

console.info(`Checking ${filename}`);
parser.write(data);
parser.end();
});
19 changes: 19 additions & 0 deletions check-examples/package.json
@@ -0,0 +1,19 @@
{
"name": "check-examples",
"version": "1.0.0",
"description": "Validate example code snippets in a W3C specification.",
"main": "check.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"linter": "eslint check.js"
},
"author": "adambe",
"dependencies": {
"babel-eslint": "^8.0.1",
"eslint": "^4.9.0",
"eslint-plugin-html": "^3.2.2",
"html-entities": "^1.2.1",
"htmlparser2": "^3.9.2",
"eslint-config-google": "^0.9.1"
}
}

0 comments on commit 0547efa

Please sign in to comment.