mirror of
https://github.com/remarkjs/remark-lint.git
synced 2024-09-11 19:57:15 +03:00
Add gap support
Gaps are nodes of (re)generated content, without positional information, which are therefore impossible to warn about. This feature adds support of the detection of those, and ignores warnings for already removed content. Closes GH-8.
This commit is contained in:
parent
b7017cbe0d
commit
136e7608b4
@ -4,29 +4,81 @@
|
||||
* @module Filter
|
||||
* @fileoverview mdast plug-in used internally by
|
||||
* mdast-lint to filter ruleId’s by enabled and disabled
|
||||
* ranges.
|
||||
* ranges, or by gaps.
|
||||
* @todo Externalise into its own repository.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var position = require('./utilities/position');
|
||||
var visit = require('./utilities/visit');
|
||||
|
||||
/**
|
||||
* Sort all `file`s messages by line/column. Note that
|
||||
* this works as a plugin, and will also sort warnings
|
||||
* added by other plug-ins before `mdast-lint` was added.
|
||||
* Remove warnings which are disabled, or are in gaps.
|
||||
*
|
||||
* @param {Node} ast - Root node.
|
||||
* @param {File} file - Virtual file.
|
||||
*/
|
||||
function transformer(ast, file) {
|
||||
var lastNode = ast.children[ast.children.length - 1];
|
||||
var gaps = [];
|
||||
var offset = 0;
|
||||
var isGap = false;
|
||||
|
||||
if (!file || !file.messages || !file.messages.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Patch a new position.
|
||||
*
|
||||
* @param {number?} [latest] - Last found position.
|
||||
*/
|
||||
function update(latest) {
|
||||
if (latest === undefined) {
|
||||
isGap = true;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (offset > latest) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isGap) {
|
||||
gaps.push({
|
||||
'start': offset,
|
||||
'end': latest
|
||||
});
|
||||
|
||||
isGap = false;
|
||||
}
|
||||
|
||||
offset = latest;
|
||||
}
|
||||
|
||||
visit(ast, function (node) {
|
||||
var start = position.start(node);
|
||||
var end = position.end(node);
|
||||
|
||||
update(start && start.offset);
|
||||
|
||||
if (!node.children) {
|
||||
update(end && end.offset);
|
||||
}
|
||||
});
|
||||
|
||||
if (offset === position.end(lastNode).offset) {
|
||||
update();
|
||||
update(file.toString().length - 1);
|
||||
}
|
||||
|
||||
file.messages = file.messages.filter(function (message) {
|
||||
var ranges = file.lintRanges[message.ruleId];
|
||||
var index = ranges && ranges.length;
|
||||
var gapIndex = gaps.length;
|
||||
var length = -1;
|
||||
var pos;
|
||||
var range;
|
||||
|
||||
if (!message.line) {
|
||||
@ -37,6 +89,17 @@ function transformer(ast, file) {
|
||||
message.column = 1;
|
||||
}
|
||||
|
||||
pos = file.positionToOffset(message);
|
||||
|
||||
while (gapIndex--) {
|
||||
if (
|
||||
gaps[gapIndex].start <= pos &&
|
||||
gaps[gapIndex].end > pos
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
while (--index > length) {
|
||||
range = ranges[index];
|
||||
|
||||
|
@ -10,16 +10,17 @@ module.exports = require('./lib');
|
||||
* @module Filter
|
||||
* @fileoverview mdast plug-in used internally by
|
||||
* mdast-lint to filter ruleId’s by enabled and disabled
|
||||
* ranges.
|
||||
* ranges, or by gaps.
|
||||
* @todo Externalise into its own repository.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var position = require('./utilities/position');
|
||||
var visit = require('./utilities/visit');
|
||||
|
||||
/**
|
||||
* Sort all `file`s messages by line/column. Note that
|
||||
* this works as a plugin, and will also sort warnings
|
||||
* added by other plug-ins before `mdast-lint` was added.
|
||||
* Remove warnings which are disabled, or are in gaps.
|
||||
*
|
||||
* @param {Node} ast - Root node.
|
||||
* @param {File} file - Virtual file.
|
||||
@ -29,6 +30,19 @@ function transformer(ast, file) {
|
||||
return;
|
||||
}
|
||||
|
||||
visit(ast, function (node) {
|
||||
var start = position.start(node);
|
||||
var end = position.end(node);
|
||||
|
||||
if (!start || start.offset === undefined) {
|
||||
// console.log('start: ', start, node);
|
||||
}
|
||||
|
||||
if (!end || end.offset === undefined) {
|
||||
// console.log('end: ', end, node);
|
||||
}
|
||||
});
|
||||
|
||||
file.messages = file.messages.filter(function (message) {
|
||||
var ranges = file.lintRanges[message.ruleId];
|
||||
var index = ranges && ranges.length;
|
||||
@ -77,7 +91,7 @@ function attacher() {
|
||||
|
||||
module.exports = attacher;
|
||||
|
||||
},{}],3:[function(require,module,exports){
|
||||
},{"./utilities/position":63,"./utilities/visit":65}],3:[function(require,module,exports){
|
||||
/**
|
||||
* @author Titus Wormer
|
||||
* @copyright 2015 Titus Wormer. All rights reserved.
|
||||
|
2
mdast-lint.min.js
vendored
2
mdast-lint.min.js
vendored
File diff suppressed because one or more lines are too long
15
readme.md
15
readme.md
@ -143,21 +143,6 @@ but the third is re-enabled):
|
||||
### Hello
|
||||
```
|
||||
|
||||
## Combining with other plug-ins
|
||||
|
||||
As noted above, **mdast-lint** is just an **mdast** plugin. Meaning, you
|
||||
can use other plug-ins together with it. Such as [mdast-toc](https://github.com/wooorm/mdast-toc),
|
||||
which will generate a table of contents for you.
|
||||
|
||||
However, these plug-ins will generate new nodes in the syntax tree, nodes
|
||||
which previously weren’t available: thus, they have no positional information,
|
||||
and **mdast-lint** cannot warn you about them.
|
||||
|
||||
Therefore, you need to do two things:
|
||||
|
||||
* Process the files twice (this is similar to how LaTeX works);
|
||||
* Ensure **mdast-lint** runs before the plug-in’s which generate content.
|
||||
|
||||
## Using mdast to fix your markdown
|
||||
|
||||
One of **mdast**’s cool parts is that it compiles to very clean, and highly
|
||||
|
10
test/fixtures/gaps-toc-final.md
vendored
Normal file
10
test/fixtures/gaps-toc-final.md
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
# Foo
|
||||
|
||||
## Table of Contents
|
||||
|
||||
This paragraph is removed by mdast-toc. However, a rule such as
|
||||
`no-consecutive-blank-lines` cannot see this node as it has no
|
||||
position. **mdast-lint** knows that this node has no positional
|
||||
information and can ignore the space between the ToC heading
|
||||
and end of the document, thus ignoring any messages between
|
||||
nodes.
|
11
test/fixtures/gaps-toc-internal.md
vendored
Normal file
11
test/fixtures/gaps-toc-internal.md
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
# Foo
|
||||
|
||||
## Table of Contents
|
||||
|
||||
This paragraph is removed by mdast-toc. However, a rule such as
|
||||
`no-consecutive-blank-lines` cannot see this node as it has no
|
||||
position. **mdast-lint** knows that this node has no positional
|
||||
information and can ignore the space between the ToC heading
|
||||
and next node, thus ignoring any messages between nodes.
|
||||
|
||||
## Bar
|
@ -11,9 +11,10 @@
|
||||
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
var assert = require('assert');
|
||||
var mdast = require('mdast');
|
||||
var File = require('mdast/lib/file');
|
||||
var assert = require('assert');
|
||||
var toc = require('mdast-toc');
|
||||
var lint = require('..');
|
||||
var plural = require('../lib/utilities/plural');
|
||||
var clean = require('./clean');
|
||||
@ -256,6 +257,41 @@ describe('External', function () {
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
/*
|
||||
* Validate gaps are ignored.
|
||||
*/
|
||||
|
||||
describe('Gaps', function () {
|
||||
it('should supports gaps in a document', function (done) {
|
||||
var file = toFile('gaps-toc-internal.md');
|
||||
var processor = mdast().use(toc).use(lint);
|
||||
|
||||
file.quiet = true;
|
||||
|
||||
processor.process(file, function (err) {
|
||||
assert(file.messages.length === 0);
|
||||
|
||||
done(err);
|
||||
});
|
||||
|
||||
// assertFile('gaps-toc-final.md', []);
|
||||
});
|
||||
|
||||
it('should supports gaps at the end of a document', function (done) {
|
||||
var file = toFile('gaps-toc-final.md');
|
||||
var processor = mdast().use(toc).use(lint);
|
||||
|
||||
file.quiet = true;
|
||||
|
||||
processor.process(file, function (err) {
|
||||
assert(file.messages.length === 0);
|
||||
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
/*
|
||||
* Validate inline en- and disabling.
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user