Skip to content

Commit 86cc213

Browse files
committed
lint output, v0.3.27
1 parent d0caf8b commit 86cc213

File tree

11 files changed

+216
-59
lines changed

11 files changed

+216
-59
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
All notable changes to this project will be documented in this file.
33
This project adheres to [Semantic Versioning](http://semver.org/).
44

5+
## [0.3.27] - 2016-03-12
6+
- lint output and show errors/warnings
7+
58
## [0.3.14] - 2016-02-26
69
### Added
710
- updated create templates

lib/build/lint.js

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
"use strict";
2+
var chalk = require('chalk');
3+
var validKeys = {
4+
project: ['title', 'description'],
5+
chapter: ['title', 'description', 'pages'],
6+
page: ['title', 'description', 'onPageComplete', 'tasks', 'video', 'link'],
7+
task: ['description', 'tests', 'actions', 'hints']
8+
};
9+
function lintOutput(json) {
10+
var invalidKeys = [];
11+
var warningKeys = [];
12+
var prKeys = Object.keys(json.project);
13+
prKeys.forEach(function (key) {
14+
if (validKeys.project.indexOf(key) < 0) {
15+
invalidKeys.push({ error: "Invalid Project key \"" + key + "\"", location: 'Project' });
16+
}
17+
});
18+
json.chapters.forEach(function (chapter, cIndex) {
19+
var chKeys = Object.keys(chapter);
20+
chKeys.forEach(function (key) {
21+
if (validKeys.chapter.indexOf(key) < 0) {
22+
invalidKeys.push({ error: "Invalid Chapter key \"" + key + "\"", location: "ch: " + (cIndex + 1) });
23+
}
24+
});
25+
if (chapter.pages && chapter.pages.length > 0) {
26+
chapter.pages.forEach(function (page, pIndex) {
27+
var pKeys = Object.keys(page);
28+
pKeys.forEach(function (key) {
29+
if (validKeys.page.indexOf(key) < 0) {
30+
invalidKeys.push({ error: "Invalid Page key \"" + key + "\"", location: "ch: " + (cIndex + 1) + ", page: " + (pIndex + 1) });
31+
}
32+
});
33+
if (page.tasks && page.tasks.length > 0) {
34+
page.tasks.forEach(function (task, tIndex) {
35+
var tKeys = Object.keys(task);
36+
tKeys.forEach(function (key) {
37+
if (validKeys.task.indexOf(key) < 0) {
38+
invalidKeys.push({ error: "Invalid Task key \"" + key + "\"", location: "ch: " + (cIndex + 1) + ", page: " + (pIndex + 1) + ", task: " + (tIndex + 1) });
39+
}
40+
});
41+
if (!task.tests || task.tests.length < 1) {
42+
invalidKeys.push({ error: 'Missing Task Test', location: "ch: " + (cIndex + 1) + ", page: " + (pIndex + 1) + ", task: " + (tIndex + 1) });
43+
}
44+
});
45+
}
46+
else {
47+
warningKeys.push({ warning: 'Missing page tasks', location: "ch: " + (cIndex + 1) + ", page: " + (pIndex + 1) });
48+
}
49+
});
50+
}
51+
else {
52+
warningKeys.push({ warning: 'Missing pages', location: "ch: " + (cIndex + 1) });
53+
}
54+
});
55+
if (warningKeys.length > 0) {
56+
warningKeys.forEach(function (w) {
57+
console.log(chalk.yellow("Warning: " + w.warning + ": ", w.location));
58+
});
59+
}
60+
if (invalidKeys.length > 0) {
61+
invalidKeys.forEach(function (e) {
62+
console.log(chalk.red("Error: " + e.error + ": ", e.location));
63+
});
64+
process.exit(1);
65+
}
66+
}
67+
exports.lintOutput = lintOutput;
68+
function isValidJSON(text) {
69+
if (!/^[\],:{}\s]*$/.test(text.replace(/\\["\\\/bfnrtu]/g, '@').
70+
replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
71+
replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
72+
console.log(chalk.red("\n Something went wrong. Build did not output valid JSON.\n "));
73+
process.exit(1);
74+
}
75+
}
76+
exports.isValidJSON = isValidJSON;
77+
function hasProjectInfo(json) {
78+
var validTitle = json.project.title.length > 0, validDescription = json.project.description.length > 0;
79+
if (!(validTitle && validDescription)) {
80+
console.log(chalk.red("\n Your tutorial is missing basic project information. Check the project title & description.\n "));
81+
process.exit(1);
82+
}
83+
}
84+
exports.hasProjectInfo = hasProjectInfo;
85+
function hasPage(json) {
86+
if (!(json.chapters[0].pages.length > 0 && !!json.chapters[0].pages[0].title)) {
87+
console.log(chalk.red("\n Your tutorial requires at least one page.\n "));
88+
process.exit(1);
89+
}
90+
}
91+
exports.hasPage = hasPage;

lib/build/linter/task-has-test.js

Whitespace-only changes.

lib/build/validators.js

Lines changed: 5 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
"use strict";
22
var chalk = require('chalk');
3+
var lint_1 = require('./lint');
34
function filePath(filePath) {
45
if (!filePath) {
56
console.log(chalk.red("\n Pass in a path to your .md file\n > coderoad build \"./src/tutorial.md\"\n "));
@@ -8,31 +9,11 @@ function filePath(filePath) {
89
}
910
exports.filePath = filePath;
1011
function result(text) {
11-
isValidJSON(text);
12+
lint_1.isValidJSON(text);
1213
var jsonObject = JSON.parse(text);
13-
hasProjectInfo(jsonObject);
14-
hasPage(jsonObject);
14+
lint_1.hasProjectInfo(jsonObject);
15+
lint_1.hasPage(jsonObject);
16+
lint_1.lintOutput(jsonObject);
1517
return true;
1618
}
1719
exports.result = result;
18-
function isValidJSON(text) {
19-
if (!/^[\],:{}\s]*$/.test(text.replace(/\\["\\\/bfnrtu]/g, '@').
20-
replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
21-
replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
22-
console.log(chalk.red("\n Something went wrong. There seems to be an error in " + filePath + ".\n "));
23-
process.exit(1);
24-
}
25-
}
26-
function hasProjectInfo(json) {
27-
var validTitle = json.project.title.length > 0, validDescription = json.project.description.length > 0;
28-
if (!(validTitle && validDescription)) {
29-
console.log(chalk.red("\n Your tutorial is missing basic project information. Check the project title & description.\n "));
30-
process.exit(1);
31-
}
32-
}
33-
function hasPage(json) {
34-
if (!(json.chapters[0].pages.length > 0 && !!json.chapters[0].pages[0].title)) {
35-
console.log(chalk.red("\n Your tutorial requires at least one page.\n "));
36-
process.exit(1);
37-
}
38-
}

lib/cli.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#! /usr/bin/env node
2+
23
"use strict";
34
var program = require('commander');
45
var chalk = require('chalk');
@@ -8,7 +9,7 @@ var search_1 = require('./search/search');
89
var tutorials_1 = require('./tutorials/tutorials');
910
var publish_1 = require('./publish/publish');
1011
program
11-
.version('0.3.26')
12+
.version('0.3.27')
1213
.usage('[options] <keywords>')
1314
.option('-b, --build [path/to/tutorial.md]', 'tutorial markdown file', /^.+\.md$/i)
1415
.option('-c, --create [name]', 'tutorial name')

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "coderoad-cli",
3-
"version": "0.3.26",
3+
"version": "0.3.27",
44
"description": "Command line interface for CodeRoad. Build project files.",
55
"keywords": [
66
"coderoad"

setup/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
"node" : ">=0.10.3"
1515
},
1616
"dependencies": {
17-
"mocha-coderoad": "^0.5.0"
17+
"mocha-coderoad": "^0.5.1"
1818
},
1919
"license": "MIT",
2020
"config": {

src/build/lint.ts

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
import * as chalk from 'chalk';
2+
3+
const validKeys = {
4+
project: ['title', 'description'],
5+
chapter: ['title', 'description', 'pages'],
6+
page: ['title', 'description', 'onPageComplete', 'tasks', 'video', 'link'],
7+
task: ['description', 'tests', 'actions', 'hints']
8+
};
9+
10+
export function lintOutput(json: CR.Output): void {
11+
let invalidKeys = [];
12+
let warningKeys = [];
13+
14+
// project
15+
let prKeys = Object.keys(json.project);
16+
prKeys.forEach((key) => {
17+
if (validKeys.project.indexOf(key) < 0) {
18+
invalidKeys.push({ error: `Invalid Project key "${key}"`, location: 'Project' });
19+
}
20+
});
21+
22+
json.chapters.forEach((chapter, cIndex) => {
23+
// chapter
24+
let chKeys = Object.keys(chapter);
25+
chKeys.forEach((key) => {
26+
if (validKeys.chapter.indexOf(key) < 0) {
27+
invalidKeys.push({ error: `Invalid Chapter key "${key}"`, location: `ch: ${cIndex + 1}` });
28+
}
29+
});
30+
31+
if (chapter.pages && chapter.pages.length > 0) {
32+
chapter.pages.forEach((page, pIndex) => {
33+
// page
34+
let pKeys = Object.keys(page);
35+
pKeys.forEach((key) => {
36+
if (validKeys.page.indexOf(key) < 0) {
37+
invalidKeys.push({ error: `Invalid Page key "${key}"`, location: `ch: ${cIndex + 1}, page: ${pIndex + 1}` });
38+
}
39+
});
40+
41+
if (page.tasks && page.tasks.length > 0) {
42+
page.tasks.forEach((task, tIndex) => {
43+
let tKeys = Object.keys(task);
44+
45+
tKeys.forEach((key) => {
46+
if (validKeys.task.indexOf(key) < 0) {
47+
invalidKeys.push({ error: `Invalid Task key "${key}"`, location: `ch: ${cIndex + 1}, page: ${pIndex + 1}, task: ${tIndex + 1}` });
48+
}
49+
});
50+
51+
if (!task.tests || task.tests.length < 1) {
52+
invalidKeys.push({ error: 'Missing Task Test', location: `ch: ${cIndex + 1}, page: ${pIndex + 1}, task: ${tIndex + 1}` });
53+
}
54+
});
55+
} else {
56+
warningKeys.push({ warning: 'Missing page tasks', location: `ch: ${cIndex + 1}, page: ${pIndex + 1}` });
57+
}
58+
});
59+
} else {
60+
warningKeys.push({ warning: 'Missing pages', location: `ch: ${cIndex + 1}` });
61+
}
62+
});
63+
64+
65+
if (warningKeys.length > 0) {
66+
warningKeys.forEach((w) => {
67+
console.log(chalk.yellow(`Warning: ${w.warning}: `, w.location));
68+
});
69+
}
70+
71+
if (invalidKeys.length > 0) {
72+
invalidKeys.forEach((e) => {
73+
console.log(chalk.red(`Error: ${e.error}: `, e.location));
74+
});
75+
76+
process.exit(1); // fail
77+
}
78+
}
79+
80+
export function isValidJSON(text: string): void {
81+
if (!/^[\],:{}\s]*$/.test(text.replace(/\\["\\\/bfnrtu]/g, '@').
82+
replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
83+
replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
84+
console.log(chalk.red(`
85+
Something went wrong. Build did not output valid JSON.
86+
`));
87+
process.exit(1); // fail
88+
}
89+
}
90+
91+
export function hasProjectInfo(json: CR.Output): void {
92+
let validTitle = json.project.title.length > 0,
93+
validDescription = json.project.description.length > 0;
94+
if (!(validTitle && validDescription)) {
95+
console.log(chalk.red(`
96+
Your tutorial is missing basic project information. Check the project title & description.
97+
`));
98+
process.exit(1); // fail
99+
}
100+
}
101+
102+
export function hasPage(json: CR.Output): void {
103+
if (!(json.chapters[0].pages.length > 0 && !!json.chapters[0].pages[0].title)) {
104+
console.log(chalk.red(`
105+
Your tutorial requires at least one page.
106+
`));
107+
process.exit(1); // fail
108+
}
109+
}

src/build/validators.ts

Lines changed: 2 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import * as chalk from 'chalk';
2+
import {isValidJSON, hasProjectInfo, hasPage, lintOutput} from './lint';
23

34
export function filePath(filePath: string): void {
45
if (!filePath) {
@@ -17,36 +18,6 @@ export function result(text: string): boolean {
1718
let jsonObject = JSON.parse(text);
1819
hasProjectInfo(jsonObject);
1920
hasPage(jsonObject);
21+
lintOutput(jsonObject);
2022
return true;
2123
}
22-
23-
function isValidJSON(text: string): void {
24-
if (!/^[\],:{}\s]*$/.test(text.replace(/\\["\\\/bfnrtu]/g, '@').
25-
replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
26-
replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
27-
console.log(chalk.red(`
28-
Something went wrong. There seems to be an error in ${filePath}.
29-
`));
30-
process.exit(1); // fail
31-
}
32-
}
33-
34-
function hasProjectInfo(json: CR.Output): void {
35-
let validTitle = json.project.title.length > 0,
36-
validDescription = json.project.description.length > 0;
37-
if (!(validTitle && validDescription)) {
38-
console.log(chalk.red(`
39-
Your tutorial is missing basic project information. Check the project title & description.
40-
`));
41-
process.exit(1); // fail
42-
}
43-
}
44-
45-
function hasPage(json: CR.Output): void {
46-
if (!(json.chapters[0].pages.length > 0 && !!json.chapters[0].pages[0].title)) {
47-
console.log(chalk.red(`
48-
Your tutorial requires at least one page.
49-
`));
50-
process.exit(1); // fail
51-
}
52-
}

src/cli.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import tutorials from './tutorials/tutorials';
99
import publish from './publish/publish';
1010

1111
program
12-
.version('0.3.26')
12+
.version('0.3.27')
1313
.usage('[options] <keywords>')
1414
.option('-b, --build [path/to/tutorial.md]', 'tutorial markdown file', /^.+\.md$/i)
1515
.option('-c, --create [name]', 'tutorial name')

tsconfig.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
"files": [
1616
"src/cli.ts",
1717
"src/build/build.ts",
18+
"src/build/lint.ts",
1819
"src/build/parser/actions.ts",
1920
"src/build/parser/chapter.ts",
2021
"src/build/parser/cleanup.ts",

0 commit comments

Comments
 (0)