mirror of
https://github.com/DavidAnson/markdownlint.git
synced 2025-09-21 21:30:47 +02:00
Allow custom file system implementation to be passed when linting or reading configuration.
This commit is contained in:
parent
b10147f16b
commit
211f09afbc
6 changed files with 277 additions and 52 deletions
|
@ -39,7 +39,7 @@
|
|||
"max-depth": "off",
|
||||
"max-lines": "off",
|
||||
"max-lines-per-function": "off",
|
||||
"max-params": ["error", 10],
|
||||
"max-params": ["off"],
|
||||
"max-statements": "off",
|
||||
"multiline-comment-style": ["error", "separate-lines"],
|
||||
"multiline-ternary": "off",
|
||||
|
|
34
README.md
34
README.md
|
@ -294,7 +294,8 @@ function markdownlint(options) { ... }
|
|||
|
||||
Type: `Object`
|
||||
|
||||
Configures the function.
|
||||
Configures the function. All properties are optional, but at least one
|
||||
of `files` or `strings` should be set to provide input.
|
||||
|
||||
##### options.customRules
|
||||
|
||||
|
@ -534,6 +535,16 @@ Each item in the top-level `Array` should be of the form:
|
|||
[ require("markdown-it-plugin"), plugin_param_0, plugin_param_1, ... ]
|
||||
```
|
||||
|
||||
##### options.fs
|
||||
|
||||
Type: `Object` implementing the [file system API](https://nodejs.org/api/fs.html)
|
||||
|
||||
In advanced scenarios, it may be desirable to bypass the default file system API.
|
||||
If a custom file system implementation is provided, `markdownlint` will use that
|
||||
instead of invoking `require("fs")`.
|
||||
|
||||
Note: The only methods called are `readFile` and `readFileSync`.
|
||||
|
||||
#### callback
|
||||
|
||||
Type: `Function` taking (`Error`, `Object`)
|
||||
|
@ -566,10 +577,11 @@ Asynchronous API:
|
|||
*
|
||||
* @param {string} file Configuration file name.
|
||||
* @param {ConfigurationParser[] | ReadConfigCallback} parsers Parsing function(s).
|
||||
* @param {Object} [fs] File system implementation.
|
||||
* @param {ReadConfigCallback} [callback] Callback (err, result) function.
|
||||
* @returns {void}
|
||||
*/
|
||||
function readConfig(file, parsers, callback) { ... }
|
||||
function readConfig(file, parsers, fs, callback) { ... }
|
||||
```
|
||||
|
||||
Synchronous API:
|
||||
|
@ -580,13 +592,14 @@ Synchronous API:
|
|||
*
|
||||
* @param {string} file Configuration file name.
|
||||
* @param {ConfigurationParser[]} [parsers] Parsing function(s).
|
||||
* @param {Object} [fs] File system implementation.
|
||||
* @returns {Configuration} Configuration object.
|
||||
*/
|
||||
function readConfigSync(file, parsers) { ... }
|
||||
function readConfigSync(file, parsers, fs) { ... }
|
||||
```
|
||||
|
||||
Promise API (in the `promises` namespace like Node.js's
|
||||
[`fs` Promises API](https://nodejs.org/api/fs.html#fs_fs_promises_api)):
|
||||
[`fs` Promises API](https://nodejs.org/api/fs.html#fs_promises_api)):
|
||||
|
||||
```js
|
||||
/**
|
||||
|
@ -594,9 +607,10 @@ Promise API (in the `promises` namespace like Node.js's
|
|||
*
|
||||
* @param {string} file Configuration file name.
|
||||
* @param {ConfigurationParser[]} [parsers] Parsing function(s).
|
||||
* @param {Object} [fs] File system implementation.
|
||||
* @returns {Promise<Configuration>} Configuration object.
|
||||
*/
|
||||
function readConfig(file, parsers) { ... }
|
||||
function readConfig(file, parsers, fs) { ... }
|
||||
```
|
||||
|
||||
#### file
|
||||
|
@ -627,6 +641,16 @@ For example:
|
|||
[ JSON.parse, require("toml").parse, require("js-yaml").load ]
|
||||
```
|
||||
|
||||
#### fs
|
||||
|
||||
Type: *Optional* `Object` implementing the [file system API](https://nodejs.org/api/fs.html)
|
||||
|
||||
In advanced scenarios, it may be desirable to bypass the default file system API.
|
||||
If a custom file system implementation is provided, `markdownlint` will use that
|
||||
instead of invoking `require("fs")`.
|
||||
|
||||
Note: The only methods called are `readFile`, `readFileSync`, and `accessSync`.
|
||||
|
||||
#### callback
|
||||
|
||||
Type: `Function` taking (`Error`, `Object`)
|
||||
|
|
|
@ -813,7 +813,6 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from) {
|
|||
to[j] = from[i];
|
||||
return to;
|
||||
};
|
||||
var fs = __webpack_require__(/*! fs */ "?ec0a");
|
||||
var path = __webpack_require__(/*! path */ "?b85c");
|
||||
var promisify = __webpack_require__(/*! util */ "?96a2").promisify;
|
||||
var markdownIt = __webpack_require__(/*! markdown-it */ "markdown-it");
|
||||
|
@ -1446,11 +1445,12 @@ function lintContent(ruleList, name, content, md, config, frontMatter, handleRul
|
|||
* @param {boolean} handleRuleFailures Whether to handle exceptions in rules.
|
||||
* @param {boolean} noInlineConfig Whether to allow inline configuration.
|
||||
* @param {number} resultVersion Version of the LintResults object to return.
|
||||
* @param {Object} fs File system implementation.
|
||||
* @param {boolean} synchronous Whether to execute synchronously.
|
||||
* @param {Function} callback Callback (err, result) function.
|
||||
* @returns {void}
|
||||
*/
|
||||
function lintFile(ruleList, file, md, config, frontMatter, handleRuleFailures, noInlineConfig, resultVersion, synchronous, callback) {
|
||||
function lintFile(ruleList, file, md, config, frontMatter, handleRuleFailures, noInlineConfig, resultVersion, fs, synchronous, callback) {
|
||||
// eslint-disable-next-line jsdoc/require-jsdoc
|
||||
function lintContentWrapper(err, content) {
|
||||
if (err) {
|
||||
|
@ -1460,7 +1460,6 @@ function lintFile(ruleList, file, md, config, frontMatter, handleRuleFailures, n
|
|||
}
|
||||
// Make a/synchronous call to read file
|
||||
if (synchronous) {
|
||||
// @ts-ignore
|
||||
lintContentWrapper(null, fs.readFileSync(file, "utf8"));
|
||||
}
|
||||
else {
|
||||
|
@ -1507,6 +1506,7 @@ function lintInput(options, synchronous, callback) {
|
|||
// @ts-ignore
|
||||
md.use.apply(md, plugin);
|
||||
});
|
||||
var fs = options.fs || __webpack_require__(/*! fs */ "?ec0a");
|
||||
var results = newResults(ruleList);
|
||||
var done = false;
|
||||
// Linting of strings is always synchronous
|
||||
|
@ -1526,7 +1526,7 @@ function lintInput(options, synchronous, callback) {
|
|||
if (synchronous) {
|
||||
// Lint files synchronously
|
||||
while (!done && (syncItem = files.shift())) {
|
||||
lintFile(ruleList, syncItem, md, config, frontMatter, handleRuleFailures, noInlineConfig, resultVersion, synchronous, syncCallback);
|
||||
lintFile(ruleList, syncItem, md, config, frontMatter, handleRuleFailures, noInlineConfig, resultVersion, fs, synchronous, syncCallback);
|
||||
}
|
||||
return done || callback(null, results);
|
||||
}
|
||||
|
@ -1540,7 +1540,7 @@ function lintInput(options, synchronous, callback) {
|
|||
}
|
||||
else if (asyncItem) {
|
||||
concurrency++;
|
||||
lintFile(ruleList, asyncItem, md, config, frontMatter, handleRuleFailures, noInlineConfig, resultVersion, synchronous, function (err, result) {
|
||||
lintFile(ruleList, asyncItem, md, config, frontMatter, handleRuleFailures, noInlineConfig, resultVersion, fs, synchronous, function (err, result) {
|
||||
concurrency--;
|
||||
if (err) {
|
||||
done = true;
|
||||
|
@ -1644,24 +1644,24 @@ function parseConfiguration(name, content, parsers) {
|
|||
*
|
||||
* @param {string} configFile Configuration file name.
|
||||
* @param {string} referenceId Referenced identifier to resolve.
|
||||
* @param {Object} fs File system implementation.
|
||||
* @returns {string} Resolved path to file.
|
||||
*/
|
||||
function resolveConfigExtends(configFile, referenceId) {
|
||||
function resolveConfigExtends(configFile, referenceId, fs) {
|
||||
var configFileDirname = path.dirname(configFile);
|
||||
var resolvedExtendsFile = path.resolve(configFileDirname, referenceId);
|
||||
try {
|
||||
if (fs.statSync(resolvedExtendsFile).isFile()) {
|
||||
return resolvedExtendsFile;
|
||||
}
|
||||
fs.accessSync(resolvedExtendsFile);
|
||||
return resolvedExtendsFile;
|
||||
}
|
||||
catch (_a) {
|
||||
// If not a file or fs.statSync throws, try require.resolve
|
||||
// Not a file, try require.resolve
|
||||
}
|
||||
try {
|
||||
return dynamicRequire.resolve(referenceId, { "paths": [configFileDirname] });
|
||||
}
|
||||
catch (_b) {
|
||||
// If require.resolve throws, return resolvedExtendsFile
|
||||
// Unable to resolve, return resolvedExtendsFile
|
||||
}
|
||||
return resolvedExtendsFile;
|
||||
}
|
||||
|
@ -1671,14 +1671,24 @@ function resolveConfigExtends(configFile, referenceId) {
|
|||
* @param {string} file Configuration file name.
|
||||
* @param {ConfigurationParser[] | ReadConfigCallback} parsers Parsing
|
||||
* function(s).
|
||||
* @param {Object} [fs] File system implementation.
|
||||
* @param {ReadConfigCallback} [callback] Callback (err, result) function.
|
||||
* @returns {void}
|
||||
*/
|
||||
function readConfig(file, parsers, callback) {
|
||||
function readConfig(file, parsers, fs, callback) {
|
||||
if (!callback) {
|
||||
// @ts-ignore
|
||||
callback = parsers;
|
||||
parsers = null;
|
||||
if (fs) {
|
||||
callback = fs;
|
||||
fs = null;
|
||||
}
|
||||
else {
|
||||
// @ts-ignore
|
||||
callback = parsers;
|
||||
parsers = null;
|
||||
}
|
||||
}
|
||||
if (!fs) {
|
||||
fs = __webpack_require__(/*! fs */ "?ec0a");
|
||||
}
|
||||
// Read file
|
||||
fs.readFile(file, "utf8", function (err, content) {
|
||||
|
@ -1695,8 +1705,8 @@ function readConfig(file, parsers, callback) {
|
|||
var configExtends = config["extends"];
|
||||
if (configExtends) {
|
||||
delete config["extends"];
|
||||
var resolvedExtends = resolveConfigExtends(file, configExtends);
|
||||
return readConfig(resolvedExtends, parsers, function (errr, extendsConfig) {
|
||||
var resolvedExtends = resolveConfigExtends(file, configExtends, fs);
|
||||
return readConfig(resolvedExtends, parsers, fs, function (errr, extendsConfig) {
|
||||
if (errr) {
|
||||
return callback(errr);
|
||||
}
|
||||
|
@ -1712,22 +1722,26 @@ var readConfigPromisify = promisify && promisify(readConfig);
|
|||
*
|
||||
* @param {string} file Configuration file name.
|
||||
* @param {ConfigurationParser[]} [parsers] Parsing function(s).
|
||||
* @param {Object} [fs] File system implementation.
|
||||
* @returns {Promise<Configuration>} Configuration object.
|
||||
*/
|
||||
function readConfigPromise(file, parsers) {
|
||||
function readConfigPromise(file, parsers, fs) {
|
||||
// @ts-ignore
|
||||
return readConfigPromisify(file, parsers);
|
||||
return readConfigPromisify(file, parsers, fs);
|
||||
}
|
||||
/**
|
||||
* Read specified configuration file synchronously.
|
||||
*
|
||||
* @param {string} file Configuration file name.
|
||||
* @param {ConfigurationParser[]} [parsers] Parsing function(s).
|
||||
* @param {Object} [fs] File system implementation.
|
||||
* @returns {Configuration} Configuration object.
|
||||
*/
|
||||
function readConfigSync(file, parsers) {
|
||||
function readConfigSync(file, parsers, fs) {
|
||||
if (!fs) {
|
||||
fs = __webpack_require__(/*! fs */ "?ec0a");
|
||||
}
|
||||
// Read file
|
||||
// @ts-ignore
|
||||
var content = fs.readFileSync(file, "utf8");
|
||||
// Try to parse file
|
||||
var _a = parseConfiguration(file, content, parsers), config = _a.config, message = _a.message;
|
||||
|
@ -1738,8 +1752,8 @@ function readConfigSync(file, parsers) {
|
|||
var configExtends = config["extends"];
|
||||
if (configExtends) {
|
||||
delete config["extends"];
|
||||
var resolvedExtends = resolveConfigExtends(file, configExtends);
|
||||
return __assign(__assign({}, readConfigSync(resolvedExtends, parsers)), config);
|
||||
var resolvedExtends = resolveConfigExtends(file, configExtends, fs);
|
||||
return __assign(__assign({}, readConfigSync(resolvedExtends, parsers, fs)), config);
|
||||
}
|
||||
return config;
|
||||
}
|
||||
|
|
13
lib/markdownlint.d.ts
vendored
13
lib/markdownlint.d.ts
vendored
|
@ -52,6 +52,10 @@ type Options = {
|
|||
* Additional plugins.
|
||||
*/
|
||||
markdownItPlugins?: Plugin[];
|
||||
/**
|
||||
* File system implementation.
|
||||
*/
|
||||
fs?: any;
|
||||
};
|
||||
/**
|
||||
* Called with the result of the lint operation.
|
||||
|
@ -70,18 +74,20 @@ declare function markdownlintSync(options: Options): LintResults;
|
|||
* @param {string} file Configuration file name.
|
||||
* @param {ConfigurationParser[] | ReadConfigCallback} parsers Parsing
|
||||
* function(s).
|
||||
* @param {Object} [fs] File system implementation.
|
||||
* @param {ReadConfigCallback} [callback] Callback (err, result) function.
|
||||
* @returns {void}
|
||||
*/
|
||||
declare function readConfig(file: string, parsers: ConfigurationParser[] | ReadConfigCallback, callback?: ReadConfigCallback): void;
|
||||
declare function readConfig(file: string, parsers: ConfigurationParser[] | ReadConfigCallback, fs?: any, callback?: ReadConfigCallback): void;
|
||||
/**
|
||||
* Read specified configuration file synchronously.
|
||||
*
|
||||
* @param {string} file Configuration file name.
|
||||
* @param {ConfigurationParser[]} [parsers] Parsing function(s).
|
||||
* @param {Object} [fs] File system implementation.
|
||||
* @returns {Configuration} Configuration object.
|
||||
*/
|
||||
declare function readConfigSync(file: string, parsers?: ConfigurationParser[]): Configuration;
|
||||
declare function readConfigSync(file: string, parsers?: ConfigurationParser[], fs?: any): Configuration;
|
||||
/**
|
||||
* Gets the (semantic) version of the library.
|
||||
*
|
||||
|
@ -364,6 +370,7 @@ declare function markdownlintPromise(options: Options): Promise<LintResults>;
|
|||
*
|
||||
* @param {string} file Configuration file name.
|
||||
* @param {ConfigurationParser[]} [parsers] Parsing function(s).
|
||||
* @param {Object} [fs] File system implementation.
|
||||
* @returns {Promise<Configuration>} Configuration object.
|
||||
*/
|
||||
declare function readConfigPromise(file: string, parsers?: ConfigurationParser[]): Promise<Configuration>;
|
||||
declare function readConfigPromise(file: string, parsers?: ConfigurationParser[], fs?: any): Promise<Configuration>;
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const { promisify } = require("util");
|
||||
const markdownIt = require("markdown-it");
|
||||
|
@ -685,6 +684,7 @@ function lintContent(
|
|||
* @param {boolean} handleRuleFailures Whether to handle exceptions in rules.
|
||||
* @param {boolean} noInlineConfig Whether to allow inline configuration.
|
||||
* @param {number} resultVersion Version of the LintResults object to return.
|
||||
* @param {Object} fs File system implementation.
|
||||
* @param {boolean} synchronous Whether to execute synchronously.
|
||||
* @param {Function} callback Callback (err, result) function.
|
||||
* @returns {void}
|
||||
|
@ -698,6 +698,7 @@ function lintFile(
|
|||
handleRuleFailures,
|
||||
noInlineConfig,
|
||||
resultVersion,
|
||||
fs,
|
||||
synchronous,
|
||||
callback) {
|
||||
// eslint-disable-next-line jsdoc/require-jsdoc
|
||||
|
@ -710,7 +711,6 @@ function lintFile(
|
|||
}
|
||||
// Make a/synchronous call to read file
|
||||
if (synchronous) {
|
||||
// @ts-ignore
|
||||
lintContentWrapper(null, fs.readFileSync(file, "utf8"));
|
||||
} else {
|
||||
fs.readFile(file, "utf8", lintContentWrapper);
|
||||
|
@ -756,6 +756,7 @@ function lintInput(options, synchronous, callback) {
|
|||
// @ts-ignore
|
||||
md.use(...plugin);
|
||||
});
|
||||
const fs = options.fs || require("fs");
|
||||
const results = newResults(ruleList);
|
||||
let done = false;
|
||||
// Linting of strings is always synchronous
|
||||
|
@ -795,6 +796,7 @@ function lintInput(options, synchronous, callback) {
|
|||
handleRuleFailures,
|
||||
noInlineConfig,
|
||||
resultVersion,
|
||||
fs,
|
||||
synchronous,
|
||||
syncCallback
|
||||
);
|
||||
|
@ -819,6 +821,7 @@ function lintInput(options, synchronous, callback) {
|
|||
handleRuleFailures,
|
||||
noInlineConfig,
|
||||
resultVersion,
|
||||
fs,
|
||||
synchronous,
|
||||
(err, result) => {
|
||||
concurrency--;
|
||||
|
@ -929,17 +932,17 @@ function parseConfiguration(name, content, parsers) {
|
|||
*
|
||||
* @param {string} configFile Configuration file name.
|
||||
* @param {string} referenceId Referenced identifier to resolve.
|
||||
* @param {Object} fs File system implementation.
|
||||
* @returns {string} Resolved path to file.
|
||||
*/
|
||||
function resolveConfigExtends(configFile, referenceId) {
|
||||
function resolveConfigExtends(configFile, referenceId, fs) {
|
||||
const configFileDirname = path.dirname(configFile);
|
||||
const resolvedExtendsFile = path.resolve(configFileDirname, referenceId);
|
||||
try {
|
||||
if (fs.statSync(resolvedExtendsFile).isFile()) {
|
||||
return resolvedExtendsFile;
|
||||
}
|
||||
fs.accessSync(resolvedExtendsFile);
|
||||
return resolvedExtendsFile;
|
||||
} catch {
|
||||
// If not a file or fs.statSync throws, try require.resolve
|
||||
// Not a file, try require.resolve
|
||||
}
|
||||
try {
|
||||
return dynamicRequire.resolve(
|
||||
|
@ -947,7 +950,7 @@ function resolveConfigExtends(configFile, referenceId) {
|
|||
{ "paths": [ configFileDirname ] }
|
||||
);
|
||||
} catch {
|
||||
// If require.resolve throws, return resolvedExtendsFile
|
||||
// Unable to resolve, return resolvedExtendsFile
|
||||
}
|
||||
return resolvedExtendsFile;
|
||||
}
|
||||
|
@ -958,14 +961,23 @@ function resolveConfigExtends(configFile, referenceId) {
|
|||
* @param {string} file Configuration file name.
|
||||
* @param {ConfigurationParser[] | ReadConfigCallback} parsers Parsing
|
||||
* function(s).
|
||||
* @param {Object} [fs] File system implementation.
|
||||
* @param {ReadConfigCallback} [callback] Callback (err, result) function.
|
||||
* @returns {void}
|
||||
*/
|
||||
function readConfig(file, parsers, callback) {
|
||||
function readConfig(file, parsers, fs, callback) {
|
||||
if (!callback) {
|
||||
// @ts-ignore
|
||||
callback = parsers;
|
||||
parsers = null;
|
||||
if (fs) {
|
||||
callback = fs;
|
||||
fs = null;
|
||||
} else {
|
||||
// @ts-ignore
|
||||
callback = parsers;
|
||||
parsers = null;
|
||||
}
|
||||
}
|
||||
if (!fs) {
|
||||
fs = require("fs");
|
||||
}
|
||||
// Read file
|
||||
fs.readFile(file, "utf8", (err, content) => {
|
||||
|
@ -982,8 +994,8 @@ function readConfig(file, parsers, callback) {
|
|||
const configExtends = config.extends;
|
||||
if (configExtends) {
|
||||
delete config.extends;
|
||||
const resolvedExtends = resolveConfigExtends(file, configExtends);
|
||||
return readConfig(resolvedExtends, parsers, (errr, extendsConfig) => {
|
||||
const resolvedExtends = resolveConfigExtends(file, configExtends, fs);
|
||||
return readConfig(resolvedExtends, parsers, fs, (errr, extendsConfig) => {
|
||||
if (errr) {
|
||||
return callback(errr);
|
||||
}
|
||||
|
@ -1004,11 +1016,12 @@ const readConfigPromisify = promisify && promisify(readConfig);
|
|||
*
|
||||
* @param {string} file Configuration file name.
|
||||
* @param {ConfigurationParser[]} [parsers] Parsing function(s).
|
||||
* @param {Object} [fs] File system implementation.
|
||||
* @returns {Promise<Configuration>} Configuration object.
|
||||
*/
|
||||
function readConfigPromise(file, parsers) {
|
||||
function readConfigPromise(file, parsers, fs) {
|
||||
// @ts-ignore
|
||||
return readConfigPromisify(file, parsers);
|
||||
return readConfigPromisify(file, parsers, fs);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1016,11 +1029,14 @@ function readConfigPromise(file, parsers) {
|
|||
*
|
||||
* @param {string} file Configuration file name.
|
||||
* @param {ConfigurationParser[]} [parsers] Parsing function(s).
|
||||
* @param {Object} [fs] File system implementation.
|
||||
* @returns {Configuration} Configuration object.
|
||||
*/
|
||||
function readConfigSync(file, parsers) {
|
||||
function readConfigSync(file, parsers, fs) {
|
||||
if (!fs) {
|
||||
fs = require("fs");
|
||||
}
|
||||
// Read file
|
||||
// @ts-ignore
|
||||
const content = fs.readFileSync(file, "utf8");
|
||||
// Try to parse file
|
||||
const { config, message } = parseConfiguration(file, content, parsers);
|
||||
|
@ -1031,9 +1047,9 @@ function readConfigSync(file, parsers) {
|
|||
const configExtends = config.extends;
|
||||
if (configExtends) {
|
||||
delete config.extends;
|
||||
const resolvedExtends = resolveConfigExtends(file, configExtends);
|
||||
const resolvedExtends = resolveConfigExtends(file, configExtends, fs);
|
||||
return {
|
||||
...readConfigSync(resolvedExtends, parsers),
|
||||
...readConfigSync(resolvedExtends, parsers, fs),
|
||||
...config
|
||||
};
|
||||
}
|
||||
|
@ -1156,6 +1172,7 @@ module.exports = markdownlint;
|
|||
* @property {boolean} [noInlineConfig] True to ignore HTML directives.
|
||||
* @property {number} [resultVersion] Results object version.
|
||||
* @property {Plugin[]} [markdownItPlugins] Additional plugins.
|
||||
* @property {Object} [fs] File system implementation.
|
||||
*/
|
||||
|
||||
/**
|
||||
|
|
|
@ -652,11 +652,13 @@ test.cb("readmeHeadings", (t) => {
|
|||
"##### options.noInlineConfig",
|
||||
"##### options.resultVersion",
|
||||
"##### options.markdownItPlugins",
|
||||
"##### options.fs",
|
||||
"#### callback",
|
||||
"#### result",
|
||||
"### Config",
|
||||
"#### file",
|
||||
"#### parsers",
|
||||
"#### fs",
|
||||
"#### callback",
|
||||
"#### result",
|
||||
"## Usage",
|
||||
|
@ -798,6 +800,40 @@ test.cb("missingStringValue", (t) => {
|
|||
});
|
||||
});
|
||||
|
||||
test("customFileSystemSync", (t) => {
|
||||
t.plan(2);
|
||||
const file = "/dir/file.md";
|
||||
const fsApi = {
|
||||
"readFileSync": (p) => {
|
||||
t.is(p, file);
|
||||
return "# Heading";
|
||||
}
|
||||
};
|
||||
const result = markdownlint.sync({
|
||||
"files": file,
|
||||
"fs": fsApi
|
||||
});
|
||||
t.deepEqual(result[file].length, 1, "Did not report violations.");
|
||||
});
|
||||
|
||||
test.cb("customFileSystemAsync", (t) => {
|
||||
t.plan(3);
|
||||
const file = "/dir/file.md";
|
||||
const fsApi = {
|
||||
"readFile": (p, o, cb) => {
|
||||
t.is(p, file);
|
||||
cb(null, "# Heading");
|
||||
}
|
||||
};
|
||||
markdownlint({
|
||||
"files": file,
|
||||
"fs": fsApi
|
||||
}, function callback(err, result) {
|
||||
t.falsy(err);
|
||||
t.deepEqual(result[file].length, 1, "Did not report violations.");
|
||||
t.end();
|
||||
});
|
||||
});
|
||||
test.cb("readme", (t) => {
|
||||
t.plan(115);
|
||||
const tagToRules = {};
|
||||
|
@ -1105,6 +1141,52 @@ test.cb("configMultipleWithRequireResolve", (t) => {
|
|||
});
|
||||
});
|
||||
|
||||
test.cb("configCustomFileSystem", (t) => {
|
||||
t.plan(5);
|
||||
const file = "/dir/file.json";
|
||||
const extended = "/dir/extended.json";
|
||||
const fileContent = {
|
||||
"extends": extended,
|
||||
"default": true,
|
||||
"MD001": false
|
||||
};
|
||||
const extendedContent = {
|
||||
"MD001": true,
|
||||
"MD002": true
|
||||
};
|
||||
const fsApi = {
|
||||
"accessSync": (p) => {
|
||||
t.is(p, extended);
|
||||
},
|
||||
"readFile": (p, o, cb) => {
|
||||
switch (p) {
|
||||
case file:
|
||||
t.is(p, file);
|
||||
return cb(null, JSON.stringify(fileContent));
|
||||
case extended:
|
||||
t.is(p, extended);
|
||||
return cb(null, JSON.stringify(extendedContent));
|
||||
default:
|
||||
return t.fail();
|
||||
}
|
||||
}
|
||||
};
|
||||
markdownlint.readConfig(
|
||||
file,
|
||||
null,
|
||||
fsApi,
|
||||
function callback(err, actual) {
|
||||
t.falsy(err);
|
||||
const expected = {
|
||||
...extendedContent,
|
||||
...fileContent
|
||||
};
|
||||
delete expected.extends;
|
||||
t.deepEqual(actual, expected, "Config object not correct.");
|
||||
t.end();
|
||||
});
|
||||
});
|
||||
|
||||
test.cb("configBadFile", (t) => {
|
||||
t.plan(4);
|
||||
markdownlint.readConfig("./test/config/config-badfile.json",
|
||||
|
@ -1358,6 +1440,45 @@ test("configMultipleHybridSync", (t) => {
|
|||
t.like(actual, expected, "Config object not correct.");
|
||||
});
|
||||
|
||||
test("configCustomFileSystemSync", (t) => {
|
||||
t.plan(4);
|
||||
const file = "/dir/file.json";
|
||||
const extended = "/dir/extended.json";
|
||||
const fileContent = {
|
||||
"extends": extended,
|
||||
"default": true,
|
||||
"MD001": false
|
||||
};
|
||||
const extendedContent = {
|
||||
"MD001": true,
|
||||
"MD002": true
|
||||
};
|
||||
const fsApi = {
|
||||
"accessSync": (p) => {
|
||||
t.is(p, extended);
|
||||
},
|
||||
"readFileSync": (p) => {
|
||||
switch (p) {
|
||||
case file:
|
||||
t.is(p, file);
|
||||
return JSON.stringify(fileContent);
|
||||
case extended:
|
||||
t.is(p, extended);
|
||||
return JSON.stringify(extendedContent);
|
||||
default:
|
||||
return t.fail();
|
||||
}
|
||||
}
|
||||
};
|
||||
const actual = markdownlint.readConfigSync(file, null, fsApi);
|
||||
const expected = {
|
||||
...extendedContent,
|
||||
...fileContent
|
||||
};
|
||||
delete expected.extends;
|
||||
t.deepEqual(actual, expected, "Config object not correct.");
|
||||
});
|
||||
|
||||
test("configBadHybridSync", (t) => {
|
||||
t.plan(1);
|
||||
t.throws(
|
||||
|
@ -1385,6 +1506,48 @@ test.cb("configSinglePromise", (t) => {
|
|||
});
|
||||
});
|
||||
|
||||
test.cb("configCustomFileSystemPromise", (t) => {
|
||||
t.plan(4);
|
||||
const file = "/dir/file.json";
|
||||
const extended = "/dir/extended.json";
|
||||
const fileContent = {
|
||||
"extends": extended,
|
||||
"default": true,
|
||||
"MD001": false
|
||||
};
|
||||
const extendedContent = {
|
||||
"MD001": true,
|
||||
"MD002": true
|
||||
};
|
||||
const fsApi = {
|
||||
"accessSync": (p) => {
|
||||
t.is(p, extended);
|
||||
},
|
||||
"readFile": (p, o, cb) => {
|
||||
switch (p) {
|
||||
case file:
|
||||
t.is(p, file);
|
||||
return cb(null, JSON.stringify(fileContent));
|
||||
case extended:
|
||||
t.is(p, extended);
|
||||
return cb(null, JSON.stringify(extendedContent));
|
||||
default:
|
||||
return t.fail();
|
||||
}
|
||||
}
|
||||
};
|
||||
markdownlint.promises.readConfig(file, null, fsApi)
|
||||
.then((actual) => {
|
||||
const expected = {
|
||||
...extendedContent,
|
||||
...fileContent
|
||||
};
|
||||
delete expected.extends;
|
||||
t.deepEqual(actual, expected, "Config object not correct.");
|
||||
t.end();
|
||||
});
|
||||
});
|
||||
|
||||
test.cb("configBadFilePromise", (t) => {
|
||||
t.plan(2);
|
||||
markdownlint.promises.readConfig("./test/config/config-badfile.json")
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue