Skip to content

Commit 1ac972c

Browse files
committed
Refactor "options" documentation logic
Use Handlebars partials and helpers to generate the markup for the "Options" page more declaratively. This requires exposing raw "options" data during site compilation and will facilitate future extensions to the interactive code editor displayed on the website's index page.
1 parent 3e38300 commit 1ac972c

File tree

7 files changed

+157
-157
lines changed

7 files changed

+157
-157
lines changed

package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
},
1919
"oddwebPlugins": [
2020
"core/blog",
21-
"plugins/options.js",
2221
"plugins/minify.js",
2322
"plugins/variables.js"
2423
],

pages/options.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,16 @@ <h3><a class="anchor" href="#enforcing-options" name="enforcing-options">Enforci
1212

1313
<p>When set to true, these options will make JSHint produce more warnings about your code.</p>
1414

15-
{{show-enforcers}}
15+
{{>option-table options.enforcers }}
1616

1717
<h3><a class="anchor" href="#relaxing-options" name="relaxing-options">Relaxing options</a></h3>
1818

1919
<p>When set to true, these options will make JSHint produce fewer warnings about your code.</p>
2020

21-
{{show-relaxers}}
21+
{{>option-table options.relaxers }}
2222

2323
<h3><a class="anchor" href="#environments" name="environments">Environments</a></h3>
2424

2525
<p>These options let JSHint know about some pre-defined global variables.</p>
2626

27-
{{show-environments}}
27+
{{>option-table options.environments }}

partials/option-table.html

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<table class='options table table-bordered table-striped'>
2+
{{#each this}}
3+
<tr>
4+
<td class="{{name}}" id="{{name}}">
5+
<a href="#{{name}}">{{name}}</a>
6+
</td>
7+
<td class="desc">
8+
{{#if deprecationReason}}
9+
<div class="deprecation-msg">
10+
<strong>Warning</strong> This option has been deprecated and will be
11+
removed in the next major release of JSHint.
12+
{{{markdown deprecationReason}}}
13+
</div>
14+
{{/if}}
15+
{{{ description.full }}}
16+
</td>
17+
</tr>
18+
{{/each}}
19+
</table>

plugins/options.js

Lines changed: 0 additions & 122 deletions
This file was deleted.

plugins/util/fenced-code.js

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
"use strict";
2+
var openPattern = /^(\s*)```[\w]*\s*$/;
3+
var closePattern = /^\s*```\s*$/;
4+
5+
/**
6+
* The Markdown preprocessor used by Oddweb does not support the
7+
* "backtick"/"code fence" syntax for multiline code examples. If present,
8+
* these must be translated to the "indented" format.
9+
*/
10+
module.exports = function(markdown) {
11+
var lines = markdown.split("\n");
12+
var state = { fixed: [], indent: '', isCode: false };
13+
14+
lines.reduce(function(state, line) {
15+
var match;
16+
if (state.isCode) {
17+
if (closePattern.test(line)) {
18+
state.isCode = false;
19+
} else {
20+
state.fixed.push(state.indent + line);
21+
}
22+
} else {
23+
match = openPattern.exec(line);
24+
if (match) {
25+
state.isCode = true;
26+
state.indent = match[1] || ' ';
27+
} else {
28+
state.fixed.push(line);
29+
}
30+
}
31+
return state;
32+
}, state);
33+
34+
return state.fixed.join("\n");
35+
}
36+

plugins/util/read-options.js

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
"use strict";
2+
var fs = require("fs");
3+
4+
var dox = require("dox");
5+
dox.setMarkedOptions({
6+
breaks: false
7+
});
8+
9+
function getCategory(annotation, options) {
10+
var value = null;
11+
var name = annotation.ctx.name;
12+
13+
if (name in options.parsed.bool.enforcing || name in options.parsed.val) {
14+
name = "enforcers";
15+
} else if (name in options.parsed.bool.relaxing) {
16+
name = "relaxers";
17+
} else if (name in options.parsed.bool.environments) {
18+
name = "environments";
19+
} else {
20+
throw new Error("Category not recognized for option ", name);
21+
}
22+
23+
return name;
24+
}
25+
26+
function getDeprecationReason(annotation) {
27+
var tags = annotation.tags;
28+
var idx, length, tag;
29+
30+
if (!tags) {
31+
return null;
32+
}
33+
34+
for (idx = 0, length = tags.length; idx < length; ++idx) {
35+
tag = tags[idx];
36+
if (tag.type === 'deprecated') {
37+
return tag.string;
38+
}
39+
}
40+
41+
return null;
42+
}
43+
44+
module.exports = function(path) {
45+
var options = {
46+
src: fs.readFileSync(path, { encoding: "utf-8" }),
47+
parsed: require(path),
48+
byCategory: {
49+
enforcers: [],
50+
relaxers: [],
51+
environments: [],
52+
legacy: []
53+
}
54+
};
55+
56+
options.annotations = dox.parseComments(options.src);
57+
58+
options.annotations.map(function(annotation) {
59+
var name = annotation.code.split(":")[0];
60+
var option = options.parsed[name];
61+
62+
annotation.name = name.trim();
63+
annotation.category = getCategory(annotation, options);
64+
annotation.deprecationReason = getDeprecationReason(annotation);
65+
66+
return annotation;
67+
}).forEach(function(annotation) {
68+
options.byCategory[annotation.category].push(annotation);
69+
});
70+
71+
Object.keys(options.byCategory).forEach(function(category) {
72+
options.byCategory[category].sort(function(a, b) {
73+
return a.name > b.name ? 1 : -1;
74+
});
75+
});
76+
77+
return options.byCategory;
78+
};

plugins/variables.js

Lines changed: 21 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@
55
"use strict";
66
var path = require("path");
77
var fs = require("fs");
8+
var marked = require("marked");
9+
var readOptions = require("./util/read-options");
10+
var translateFencedCode = require("./util/fenced-code");
11+
var optionsSrc = __dirname + "/../res/jshint/src/options.js";
812

913
var pkg = require(path.join(
1014
__dirname, "..", "res", "jshint", "package.json")
@@ -15,6 +19,7 @@ var contributing = fs.readFileSync(
1519
var context = {
1620
contributionGuidelines: translateFencedCode(contributing),
1721
version: pkg.version,
22+
options: readOptions(optionsSrc),
1823
urls: {
1924
repo: "https://github.com/jshint/jshint",
2025
newIssue: "https://github.com/jshint/jshint/issues/new",
@@ -23,41 +28,26 @@ var context = {
2328
}
2429
};
2530

26-
/**
27-
* The Markdown preprocessor used by Oddweb does not support the
28-
* "backtick"/"code fence" syntax for multiline code examples. If present,
29-
* these must be translated to the "indented" format.
30-
*/
31-
function translateFencedCode(markdown) {
32-
var openPattern = /^(\s*)```[\w]*\s*$/;
33-
var closePattern = /^\s*```\s*$/;
34-
var lines = markdown.split("\n");
35-
var state = { fixed: [], indent: '', isCode: false };
31+
module.exports = function (site, handlebars) {
32+
var partialPattern = /^(.*)\.html$/i;
33+
34+
handlebars.registerHelper("markdown", function (input) {
35+
return new handlebars.SafeString(marked(input));
36+
});
37+
38+
fs.readdirSync("partials").forEach(function(filename) {
39+
var match = filename.match(partialPattern);
3640

37-
lines.reduce(function(state, line) {
38-
var match;
39-
if (state.isCode) {
40-
if (closePattern.test(line)) {
41-
state.isCode = false;
42-
} else {
43-
state.fixed.push(state.indent + line);
44-
}
45-
} else {
46-
match = openPattern.exec(line);
47-
if (match) {
48-
state.isCode = true;
49-
state.indent = match[1] || ' ';
50-
} else {
51-
state.fixed.push(line);
52-
}
41+
if (!match) {
42+
return null;
5343
}
54-
return state;
55-
}, state);
5644

57-
return state.fixed.join("\n");
58-
}
45+
handlebars.registerPartial(
46+
match[1],
47+
fs.readFileSync(path.join("partials", filename), { encoding: "utf-8" })
48+
);
49+
});
5950

60-
module.exports = function (site, handlebars) {
6151
site.pages.forEach(function(page) {
6252
var template = handlebars.compile(page.data);
6353
page.data = template(context);

0 commit comments

Comments
 (0)