-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathspellcheck.js
102 lines (82 loc) · 2.54 KB
/
spellcheck.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
var aspell = require('aspell'),
Promise = require('promise'),
Queue = require('promise-queue');
Queue.configure(Promise);
var queue = new Queue(5, Infinity);
module.exports = {
name: 'spellcheck',
on: ['dom'],
filter: ['text', 'tag']
};
module.exports.lint = function (element, opts) {
var lang = opts[this.name],
issues = null;
if (!lang || !this.isViewableElement(element)) {
return [];
}
if (element.type === 'text') {
return this.spellcheck(element.data, element.lineCol);
} else if (element.attribs) {
return this.lintAttribs(element.attribs);
}
return [];
};
module.exports.isViewableElement = function (element) {
var parent = element;
while (parent) {
if (parent.type === 'script' ||
parent.type === 'style') {
return false;
}
parent = parent.parent;
}
return true;
};
module.exports.lintAttribs = function (attribs) {
var issues = [];
Object.keys(attribs).forEach(function (attribName) {
var attrib = attribs[attribName],
newIssues = null;
if (!this.isViewableAttrib(attribName)) {
return;
}
newIssues = this.spellcheck(attrib.value, attrib.valueLineCol);
issues = issues.concat(newIssues);
}.bind(this));
return issues;
};
var viewableAttribs = ['title', 'alt'];
module.exports.isViewableAttrib = function (attribName) {
var lowercaseName = attribName.toLowerCase();
return (viewableAttribs.indexOf(lowercaseName) > -1);
};
module.exports.spellcheck = function (text, pos) {
return queue.add(function () {
return this.spawnSpellcheck(text, pos);
}.bind(this));
};
module.exports.spawnSpellcheck = function (text, pos) {
return new Promise(function (resolve, reject) {
var emitter = aspell(text),
issues = [],
line = 0;
emitter.on('error', function (chunk) {
// TODO: how to handle errors in rules?
reject(issues);
});
emitter.on('result', function (result) {
if (result.type === 'line-break') {
line += 1;
} else if (result.type === 'misspelling') {
issues.push({
msg: 'Misspelling: ' + result.word,
line: pos[0] + line,
column: (line ? result.position : result.position + pos[1])
});
}
});
emitter.on('end', function () {
resolve(issues);
});
});
};