forked from tmcw/docbox
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathcontent.js
119 lines (106 loc) · 3.89 KB
/
content.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
/* global it describe */
var remark = require('remark');
var expect = require('expect');
var visit = require('unist-util-visit');
var select = require('unist-util-select');
var fs = require('fs');
var GithubSlugger = require('github-slugger');
var { linter } = require('eslint');
var allPages = require('../src/custom/content');
var slugger = new GithubSlugger();
var actionVerbs = /^(List|Retrieve|Remove|Search|Create|Delete)/;
let isSectionTitle = (title) => title.match(actionVerbs);
let getSectionTitle = chunk => chunk[0].children[0].value;
function extractSections(ast) {
return ast.children.reduce((chunks, node) => {
if (node.type === 'heading' && node.depth === 1) {
return chunks;
} else if (node.type === 'heading' && node.depth === 3) {
chunks.push([node]);
} else {
chunks[chunks.length - 1].push(node);
}
return chunks;
}, [[]])
.filter(chunk => chunk.length)
.filter(chunk => {
return isSectionTitle(getSectionTitle(chunk));
})
.map(chunk => ({ type: 'root', children: chunk }));
}
var slugs = {};
describe('global rules', () => {
var ast = remark().parse(allPages);
var seen = {};
/**
* Check that titles are unique. This is to ensure that permalinks
* are unique.
*/
visit(ast, 'heading', node => {
slugs['#' + slugger.slug(node.children[0].value)] = true;
if (node.depth > 3) return;
var { value } = node.children[0];
it('title ' + value + ' is unique', () => {
expect(seen.hasOwnProperty(value))
.toEqual(false, 'Title `' + value + '` should be unique');
seen[value] = true;
});
});
});
describe('content', () => {
fs.readdirSync('./content').forEach(function(file) {
describe(file, () => {
var content = fs.readFileSync('./content/' + file, 'utf8');
var ast = remark().parse(content);
it('links are valid', function() {
visit(ast, 'link', node => {
if (node.href && node.href[0] === '#') {
expect(slugs[node.href])
.toExist('A link to ' + node.href + ' at ' +
node.position.start.line + ' of ' + file + ' was invalid');
}
});
});
it('has h2 title', function() {
expect(ast.children[0].type).toEqual('heading');
expect(ast.children[0].depth).toEqual(2);
});
it('has API description', function() {
expect(ast.children[1].type === 'paragraph' || ast.children[1].type === 'html').toEqual(true);
});
it('has valid json', () => {
select(ast, 'code[lang=json]').forEach(node => {
expect(function() {
JSON.parse(node.value);
}).not.toThrow('a JSON code block at L:' +
node.position.start.line + ' of ' + file + ' was invalid');
});
});
it('has valid javascript', () => {
select(ast, 'code[lang=javascript]').forEach(node => {
var messages = linter.verify(node.value);
expect(messages).toEqual([], 'a JS code block at L:' +
node.position.start.line + ' of ' + file + ' was invalid');
});
});
extractSections(ast).forEach(chunk => {
describe(getSectionTitle(chunk.children), function() {
it('has an endpoint and that endpoint has a valid method', () => {
var endpoint = select(chunk, 'code[lang=endpoint]');
expect(endpoint.length).toBeGreaterThan(0);
expect(endpoint[0].value.toString()).toMatch(/^(PUT|POST|GET|DELETE|PATCH)/);
});
it('has python example', () => {
expect(select(chunk, 'code[lang=python]').length).toBeGreaterThan(0);
});
it('has js example', () => {
expect(select(chunk, 'code[lang=javascript]').length).toBeGreaterThan(0);
});
it('has curl example', () => {
expect(select(chunk, 'code[lang=curl]').length).toBeGreaterThan(0);
});
});
});
});
});
});