2015-06-02 09:34:14 +03:00
|
|
|
/**
|
|
|
|
* @author Titus Wormer
|
2015-08-17 14:48:19 +03:00
|
|
|
* @copyright 2015 Titus Wormer
|
|
|
|
* @license MIT
|
2015-06-02 09:34:14 +03:00
|
|
|
* @module fenced-code-marker
|
|
|
|
* @fileoverview
|
|
|
|
* Warn for violating fenced code markers.
|
|
|
|
*
|
2017-08-17 14:52:59 +03:00
|
|
|
* Options: `` '`' ``, `'~'`, or `'consistent'`, default: `'consistent'`.
|
2015-06-02 09:34:14 +03:00
|
|
|
*
|
2017-08-17 14:52:59 +03:00
|
|
|
* `'consistent'` detects the first used fenced code marker style and warns
|
|
|
|
* when subsequent fenced code-blocks use different styles.
|
2016-08-02 23:47:01 +03:00
|
|
|
*
|
2017-02-23 20:07:52 +03:00
|
|
|
* @example {"name": "valid.md"}
|
|
|
|
*
|
|
|
|
* Indented code blocks are not affected by this rule:
|
|
|
|
*
|
|
|
|
* bravo();
|
|
|
|
*
|
2016-08-02 23:47:01 +03:00
|
|
|
* @example {"name": "valid.md", "setting": "`"}
|
|
|
|
*
|
|
|
|
* ```alpha
|
|
|
|
* bravo();
|
2015-08-17 14:57:43 +03:00
|
|
|
* ```
|
2015-06-02 09:34:14 +03:00
|
|
|
*
|
2015-08-17 14:57:43 +03:00
|
|
|
* ```
|
2016-08-02 23:47:01 +03:00
|
|
|
* charlie();
|
2015-08-17 14:57:43 +03:00
|
|
|
* ```
|
2015-06-02 09:34:14 +03:00
|
|
|
*
|
2016-08-02 23:47:01 +03:00
|
|
|
* @example {"name": "valid.md", "setting": "~"}
|
|
|
|
*
|
|
|
|
* ~~~alpha
|
|
|
|
* bravo();
|
2015-08-17 14:57:43 +03:00
|
|
|
* ~~~
|
2015-06-02 09:34:14 +03:00
|
|
|
*
|
2015-08-17 14:57:43 +03:00
|
|
|
* ~~~
|
2016-08-02 23:47:01 +03:00
|
|
|
* charlie();
|
2015-08-17 14:57:43 +03:00
|
|
|
* ~~~
|
2015-06-02 09:34:14 +03:00
|
|
|
*
|
2016-08-02 23:47:01 +03:00
|
|
|
* @example {"name": "invalid.md", "label": "input"}
|
2015-06-02 09:34:14 +03:00
|
|
|
*
|
2016-08-02 23:47:01 +03:00
|
|
|
* ```alpha
|
|
|
|
* bravo();
|
2015-08-17 14:57:43 +03:00
|
|
|
* ```
|
2016-08-02 23:47:01 +03:00
|
|
|
*
|
|
|
|
* ~~~
|
|
|
|
* charlie();
|
|
|
|
* ~~~
|
|
|
|
*
|
|
|
|
* @example {"name": "invalid.md", "label": "output"}
|
|
|
|
*
|
2017-08-17 14:52:59 +03:00
|
|
|
* 5:1-7:4: Fenced code should use ` as a marker
|
2016-08-02 23:47:01 +03:00
|
|
|
*
|
|
|
|
* @example {"name": "invalid.md", "setting": "!", "label": "output", "config": {"positionless": true}}
|
|
|
|
*
|
|
|
|
* 1:1: Invalid fenced code marker `!`: use either `'consistent'`, `` '`' ``, or `'~'`
|
2015-06-02 09:34:14 +03:00
|
|
|
*/
|
|
|
|
|
|
|
|
'use strict';
|
|
|
|
|
2017-02-23 20:07:52 +03:00
|
|
|
var rule = require('unified-lint-rule');
|
2015-08-08 16:34:40 +03:00
|
|
|
var visit = require('unist-util-visit');
|
2016-08-01 19:09:58 +03:00
|
|
|
var position = require('unist-util-position');
|
2016-11-26 18:54:16 +03:00
|
|
|
var generated = require('unist-util-generated');
|
2015-06-02 09:34:14 +03:00
|
|
|
|
2017-02-23 20:07:52 +03:00
|
|
|
module.exports = rule('remark-lint:fenced-code-marker', fencedCodeMarker);
|
2015-06-02 09:34:14 +03:00
|
|
|
|
|
|
|
var MARKERS = {
|
2016-08-01 21:41:43 +03:00
|
|
|
'`': true,
|
|
|
|
'~': true,
|
2016-10-11 12:47:14 +03:00
|
|
|
null: true
|
2015-06-02 09:34:14 +03:00
|
|
|
};
|
|
|
|
|
2016-08-01 21:41:43 +03:00
|
|
|
function fencedCodeMarker(ast, file, preferred) {
|
|
|
|
var contents = file.toString();
|
2015-06-02 09:34:14 +03:00
|
|
|
|
2016-08-01 21:41:43 +03:00
|
|
|
preferred = typeof preferred !== 'string' || preferred === 'consistent' ? null : preferred;
|
2015-06-02 09:34:14 +03:00
|
|
|
|
2016-08-01 21:41:43 +03:00
|
|
|
if (MARKERS[preferred] !== true) {
|
|
|
|
file.fail('Invalid fenced code marker `' + preferred + '`: use either `\'consistent\'`, `` \'`\' ``, or `\'~\'`');
|
|
|
|
}
|
2015-06-02 09:34:14 +03:00
|
|
|
|
2017-02-23 20:07:52 +03:00
|
|
|
visit(ast, 'code', visitor);
|
|
|
|
|
|
|
|
function visitor(node) {
|
2016-08-01 21:41:43 +03:00
|
|
|
var marker = contents.substr(position.start(node).offset, 4);
|
2015-06-02 09:34:14 +03:00
|
|
|
|
2016-11-26 18:54:16 +03:00
|
|
|
if (generated(node)) {
|
2016-08-01 21:41:43 +03:00
|
|
|
return;
|
|
|
|
}
|
2015-06-02 09:34:14 +03:00
|
|
|
|
2016-08-01 21:41:43 +03:00
|
|
|
marker = marker.trimLeft().charAt(0);
|
2015-06-02 09:34:14 +03:00
|
|
|
|
2016-08-01 21:41:43 +03:00
|
|
|
/* Ignore unfenced code blocks. */
|
|
|
|
if (MARKERS[marker] !== true) {
|
|
|
|
return;
|
|
|
|
}
|
2015-06-02 09:34:14 +03:00
|
|
|
|
2016-08-01 21:41:43 +03:00
|
|
|
if (preferred) {
|
|
|
|
if (marker !== preferred) {
|
2016-08-22 00:46:21 +03:00
|
|
|
file.message('Fenced code should use ' + preferred + ' as a marker', node);
|
2016-08-01 21:41:43 +03:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
preferred = marker;
|
|
|
|
}
|
2017-02-23 20:07:52 +03:00
|
|
|
}
|
2015-06-02 09:34:14 +03:00
|
|
|
}
|