mirror of
https://github.com/DavidAnson/markdownlint.git
synced 2025-12-17 06:20:12 +01:00
Implement (undocumented, promise-only) extendConfig API for readConfig-like behavior when the Configuration object is already available (i.e., to implement "extends" consistently).
This commit is contained in:
parent
953165a219
commit
2ab546bec0
4 changed files with 188 additions and 50 deletions
|
|
@ -2828,6 +2828,53 @@ function resolveConfigExtendsSync(configFile, referenceId, fs) {
|
||||||
return resolvedExtendsFile;
|
return resolvedExtendsFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extend specified configuration object.
|
||||||
|
*
|
||||||
|
* @param {Configuration} config Configuration object.
|
||||||
|
* @param {string} file Configuration file name.
|
||||||
|
* @param {ConfigurationParser[]} parsers Parsing
|
||||||
|
* function(s).
|
||||||
|
* @param {Object} fs File system implementation.
|
||||||
|
* @param {ReadConfigCallback} callback Callback (err, result) function.
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
function extendConfig(config, file, parsers, fs, callback) {
|
||||||
|
var configExtends = config["extends"];
|
||||||
|
if (configExtends) {
|
||||||
|
return resolveConfigExtends(file, helpers.expandTildePath(configExtends, __webpack_require__(/*! node:os */ "?e6c4")), fs,
|
||||||
|
// eslint-disable-next-line no-use-before-define
|
||||||
|
function (_, resolvedExtends) {
|
||||||
|
return readConfig(
|
||||||
|
// @ts-ignore
|
||||||
|
resolvedExtends, parsers, fs, function (err, extendsConfig) {
|
||||||
|
if (err) {
|
||||||
|
return callback(err);
|
||||||
|
}
|
||||||
|
var result = _objectSpread(_objectSpread({}, extendsConfig), config);
|
||||||
|
delete result["extends"];
|
||||||
|
return callback(null, result);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return callback(null, config);
|
||||||
|
}
|
||||||
|
var extendConfigPromisify = promisify && promisify(extendConfig);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extend specified configuration object.
|
||||||
|
*
|
||||||
|
* @param {Configuration} config Configuration object.
|
||||||
|
* @param {string} file Configuration file name.
|
||||||
|
* @param {ConfigurationParser[]} [parsers] Parsing function(s).
|
||||||
|
* @param {Object} [fs] File system implementation.
|
||||||
|
* @returns {Promise<Configuration>} Configuration object.
|
||||||
|
*/
|
||||||
|
function extendConfigPromise(config, file, parsers, fs) {
|
||||||
|
// @ts-ignore
|
||||||
|
return extendConfigPromisify(config, file, parsers, fs);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read specified configuration file.
|
* Read specified configuration file.
|
||||||
*
|
*
|
||||||
|
|
@ -2854,8 +2901,7 @@ function readConfig(file, parsers, fs, callback) {
|
||||||
fs = __webpack_require__(/*! node:fs */ "?d0ee");
|
fs = __webpack_require__(/*! node:fs */ "?d0ee");
|
||||||
}
|
}
|
||||||
// Read file
|
// Read file
|
||||||
var os = __webpack_require__(/*! node:os */ "?e6c4");
|
file = helpers.expandTildePath(file, __webpack_require__(/*! node:os */ "?e6c4"));
|
||||||
file = helpers.expandTildePath(file, os);
|
|
||||||
fs.readFile(file, "utf8", function (err, content) {
|
fs.readFile(file, "utf8", function (err, content) {
|
||||||
if (err) {
|
if (err) {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
|
|
@ -2871,24 +2917,8 @@ function readConfig(file, parsers, fs, callback) {
|
||||||
return callback(new Error(message));
|
return callback(new Error(message));
|
||||||
}
|
}
|
||||||
// Extend configuration
|
// Extend configuration
|
||||||
var configExtends = config["extends"];
|
|
||||||
if (configExtends) {
|
|
||||||
delete config["extends"];
|
|
||||||
return resolveConfigExtends(file, helpers.expandTildePath(configExtends, os), fs, function (_, resolvedExtends) {
|
|
||||||
return readConfig(
|
|
||||||
// @ts-ignore
|
|
||||||
resolvedExtends, parsers, fs, function (errr, extendsConfig) {
|
|
||||||
if (errr) {
|
|
||||||
// @ts-ignore
|
|
||||||
return callback(errr);
|
|
||||||
}
|
|
||||||
// @ts-ignore
|
|
||||||
return callback(null, _objectSpread(_objectSpread({}, extendsConfig), config));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
return callback(null, config);
|
return extendConfig(config, file, parsers, fs, callback);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
var readConfigPromisify = promisify && promisify(readConfig);
|
var readConfigPromisify = promisify && promisify(readConfig);
|
||||||
|
|
@ -2956,6 +2986,7 @@ markdownlint.readConfigSync = readConfigSync;
|
||||||
markdownlint.getVersion = getVersion;
|
markdownlint.getVersion = getVersion;
|
||||||
markdownlint.promises = {
|
markdownlint.promises = {
|
||||||
"markdownlint": markdownlintPromise,
|
"markdownlint": markdownlintPromise,
|
||||||
|
"extendConfig": extendConfigPromise,
|
||||||
"readConfig": readConfigPromise
|
"readConfig": readConfigPromise
|
||||||
};
|
};
|
||||||
module.exports = markdownlint;
|
module.exports = markdownlint;
|
||||||
|
|
|
||||||
11
lib/markdownlint.d.ts
vendored
11
lib/markdownlint.d.ts
vendored
|
|
@ -101,6 +101,7 @@ declare function readConfigSync(file: string, parsers?: ConfigurationParser[], f
|
||||||
declare function getVersion(): string;
|
declare function getVersion(): string;
|
||||||
declare namespace promises {
|
declare namespace promises {
|
||||||
export { markdownlintPromise as markdownlint };
|
export { markdownlintPromise as markdownlint };
|
||||||
|
export { extendConfigPromise as extendConfig };
|
||||||
export { readConfigPromise as readConfig };
|
export { readConfigPromise as readConfig };
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
|
@ -378,6 +379,16 @@ type ResolveConfigExtendsCallback = (err: Error | null, path?: string) => void;
|
||||||
* @returns {Promise<LintResults>} Results object.
|
* @returns {Promise<LintResults>} Results object.
|
||||||
*/
|
*/
|
||||||
declare function markdownlintPromise(options: Options): Promise<LintResults>;
|
declare function markdownlintPromise(options: Options): Promise<LintResults>;
|
||||||
|
/**
|
||||||
|
* Extend specified configuration object.
|
||||||
|
*
|
||||||
|
* @param {Configuration} config Configuration object.
|
||||||
|
* @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 extendConfigPromise(config: Configuration, file: string, parsers?: ConfigurationParser[], fs?: any): Promise<Configuration>;
|
||||||
/**
|
/**
|
||||||
* Read specified configuration file.
|
* Read specified configuration file.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -1079,6 +1079,63 @@ function resolveConfigExtendsSync(configFile, referenceId, fs) {
|
||||||
return resolvedExtendsFile;
|
return resolvedExtendsFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extend specified configuration object.
|
||||||
|
*
|
||||||
|
* @param {Configuration} config Configuration object.
|
||||||
|
* @param {string} file Configuration file name.
|
||||||
|
* @param {ConfigurationParser[]} parsers Parsing
|
||||||
|
* function(s).
|
||||||
|
* @param {Object} fs File system implementation.
|
||||||
|
* @param {ReadConfigCallback} callback Callback (err, result) function.
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
function extendConfig(config, file, parsers, fs, callback) {
|
||||||
|
const configExtends = config.extends;
|
||||||
|
if (configExtends) {
|
||||||
|
return resolveConfigExtends(
|
||||||
|
file,
|
||||||
|
helpers.expandTildePath(configExtends, require("node:os")),
|
||||||
|
fs,
|
||||||
|
// eslint-disable-next-line no-use-before-define
|
||||||
|
(_, resolvedExtends) => readConfig(
|
||||||
|
// @ts-ignore
|
||||||
|
resolvedExtends,
|
||||||
|
parsers,
|
||||||
|
fs,
|
||||||
|
(err, extendsConfig) => {
|
||||||
|
if (err) {
|
||||||
|
return callback(err);
|
||||||
|
}
|
||||||
|
const result = {
|
||||||
|
...extendsConfig,
|
||||||
|
...config
|
||||||
|
};
|
||||||
|
delete result.extends;
|
||||||
|
return callback(null, result);
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return callback(null, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
const extendConfigPromisify = promisify && promisify(extendConfig);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extend specified configuration object.
|
||||||
|
*
|
||||||
|
* @param {Configuration} config Configuration object.
|
||||||
|
* @param {string} file Configuration file name.
|
||||||
|
* @param {ConfigurationParser[]} [parsers] Parsing function(s).
|
||||||
|
* @param {Object} [fs] File system implementation.
|
||||||
|
* @returns {Promise<Configuration>} Configuration object.
|
||||||
|
*/
|
||||||
|
function extendConfigPromise(config, file, parsers, fs) {
|
||||||
|
// @ts-ignore
|
||||||
|
return extendConfigPromisify(config, file, parsers, fs);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read specified configuration file.
|
* Read specified configuration file.
|
||||||
*
|
*
|
||||||
|
|
@ -1105,8 +1162,7 @@ function readConfig(file, parsers, fs, callback) {
|
||||||
fs = require("node:fs");
|
fs = require("node:fs");
|
||||||
}
|
}
|
||||||
// Read file
|
// Read file
|
||||||
const os = require("node:os");
|
file = helpers.expandTildePath(file, require("node:os"));
|
||||||
file = helpers.expandTildePath(file, os);
|
|
||||||
fs.readFile(file, "utf8", (err, content) => {
|
fs.readFile(file, "utf8", (err, content) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
|
|
@ -1120,34 +1176,8 @@ function readConfig(file, parsers, fs, callback) {
|
||||||
return callback(new Error(message));
|
return callback(new Error(message));
|
||||||
}
|
}
|
||||||
// Extend configuration
|
// Extend configuration
|
||||||
const configExtends = config.extends;
|
|
||||||
if (configExtends) {
|
|
||||||
delete config.extends;
|
|
||||||
return resolveConfigExtends(
|
|
||||||
file,
|
|
||||||
helpers.expandTildePath(configExtends, os),
|
|
||||||
fs,
|
|
||||||
(_, resolvedExtends) => readConfig(
|
|
||||||
// @ts-ignore
|
|
||||||
resolvedExtends,
|
|
||||||
parsers,
|
|
||||||
fs,
|
|
||||||
(errr, extendsConfig) => {
|
|
||||||
if (errr) {
|
|
||||||
// @ts-ignore
|
|
||||||
return callback(errr);
|
|
||||||
}
|
|
||||||
// @ts-ignore
|
|
||||||
return callback(null, {
|
|
||||||
...extendsConfig,
|
|
||||||
...config
|
|
||||||
});
|
|
||||||
}
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
return callback(null, config);
|
return extendConfig(config, file, parsers, fs, callback);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1221,6 +1251,7 @@ markdownlint.readConfigSync = readConfigSync;
|
||||||
markdownlint.getVersion = getVersion;
|
markdownlint.getVersion = getVersion;
|
||||||
markdownlint.promises = {
|
markdownlint.promises = {
|
||||||
"markdownlint": markdownlintPromise,
|
"markdownlint": markdownlintPromise,
|
||||||
|
"extendConfig": extendConfigPromise,
|
||||||
"readConfig": readConfigPromise
|
"readConfig": readConfigPromise
|
||||||
};
|
};
|
||||||
module.exports = markdownlint;
|
module.exports = markdownlint;
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,7 @@ test("configMultiple", (t) => new Promise((resolve) => {
|
||||||
...require("./config/config-parent.json"),
|
...require("./config/config-parent.json"),
|
||||||
...require("./config/config-grandparent.json")
|
...require("./config/config-grandparent.json")
|
||||||
};
|
};
|
||||||
|
// @ts-ignore
|
||||||
delete expected.extends;
|
delete expected.extends;
|
||||||
t.deepEqual(actual, expected, "Config object not correct.");
|
t.deepEqual(actual, expected, "Config object not correct.");
|
||||||
resolve();
|
resolve();
|
||||||
|
|
@ -70,6 +71,7 @@ test("configMultipleWithRequireResolve", (t) => new Promise((resolve) => {
|
||||||
...require("./node_modules/pseudo-package/config-frompackage.json"),
|
...require("./node_modules/pseudo-package/config-frompackage.json"),
|
||||||
...require("./config/config-packageparent.json")
|
...require("./config/config-packageparent.json")
|
||||||
};
|
};
|
||||||
|
// @ts-ignore
|
||||||
delete expected.extends;
|
delete expected.extends;
|
||||||
t.deepEqual(actual, expected, "Config object not correct.");
|
t.deepEqual(actual, expected, "Config object not correct.");
|
||||||
resolve();
|
resolve();
|
||||||
|
|
@ -106,6 +108,7 @@ test("configCustomFileSystem", (t) => new Promise((resolve) => {
|
||||||
};
|
};
|
||||||
markdownlint.readConfig(
|
markdownlint.readConfig(
|
||||||
file,
|
file,
|
||||||
|
// @ts-ignore
|
||||||
null,
|
null,
|
||||||
fsApi,
|
fsApi,
|
||||||
function callback(err, actual) {
|
function callback(err, actual) {
|
||||||
|
|
@ -114,6 +117,7 @@ test("configCustomFileSystem", (t) => new Promise((resolve) => {
|
||||||
...extendedContent,
|
...extendedContent,
|
||||||
...fileContent
|
...fileContent
|
||||||
};
|
};
|
||||||
|
// @ts-ignore
|
||||||
delete expected.extends;
|
delete expected.extends;
|
||||||
t.deepEqual(actual, expected, "Config object not correct.");
|
t.deepEqual(actual, expected, "Config object not correct.");
|
||||||
resolve();
|
resolve();
|
||||||
|
|
@ -210,6 +214,7 @@ test("configMultipleYaml", (t) => new Promise((resolve) => {
|
||||||
...require("./config/config-parent.json"),
|
...require("./config/config-parent.json"),
|
||||||
...require("./config/config-grandparent.json")
|
...require("./config/config-grandparent.json")
|
||||||
};
|
};
|
||||||
|
// @ts-ignore
|
||||||
delete expected.extends;
|
delete expected.extends;
|
||||||
t.deepEqual(actual, expected, "Config object not correct.");
|
t.deepEqual(actual, expected, "Config object not correct.");
|
||||||
resolve();
|
resolve();
|
||||||
|
|
@ -229,6 +234,7 @@ test("configMultipleHybrid", (t) => new Promise((resolve) => {
|
||||||
...require("./config/config-parent.json"),
|
...require("./config/config-parent.json"),
|
||||||
...require("./config/config-grandparent.json")
|
...require("./config/config-grandparent.json")
|
||||||
};
|
};
|
||||||
|
// @ts-ignore
|
||||||
delete expected.extends;
|
delete expected.extends;
|
||||||
t.like(actual, expected, "Config object not correct.");
|
t.like(actual, expected, "Config object not correct.");
|
||||||
resolve();
|
resolve();
|
||||||
|
|
@ -287,6 +293,7 @@ test("configMultipleSync", (t) => {
|
||||||
...require("./config/config-parent.json"),
|
...require("./config/config-parent.json"),
|
||||||
...require("./config/config-grandparent.json")
|
...require("./config/config-grandparent.json")
|
||||||
};
|
};
|
||||||
|
// @ts-ignore
|
||||||
delete expected.extends;
|
delete expected.extends;
|
||||||
t.deepEqual(actual, expected, "Config object not correct.");
|
t.deepEqual(actual, expected, "Config object not correct.");
|
||||||
});
|
});
|
||||||
|
|
@ -366,6 +373,7 @@ test("configMultipleYamlSync", (t) => {
|
||||||
...require("./config/config-parent.json"),
|
...require("./config/config-parent.json"),
|
||||||
...require("./config/config-grandparent.json")
|
...require("./config/config-grandparent.json")
|
||||||
};
|
};
|
||||||
|
// @ts-ignore
|
||||||
delete expected.extends;
|
delete expected.extends;
|
||||||
t.deepEqual(actual, expected, "Config object not correct.");
|
t.deepEqual(actual, expected, "Config object not correct.");
|
||||||
});
|
});
|
||||||
|
|
@ -381,6 +389,7 @@ test("configMultipleHybridSync", (t) => {
|
||||||
...require("./config/config-parent.json"),
|
...require("./config/config-parent.json"),
|
||||||
...require("./config/config-grandparent.json")
|
...require("./config/config-grandparent.json")
|
||||||
};
|
};
|
||||||
|
// @ts-ignore
|
||||||
delete expected.extends;
|
delete expected.extends;
|
||||||
t.like(actual, expected, "Config object not correct.");
|
t.like(actual, expected, "Config object not correct.");
|
||||||
});
|
});
|
||||||
|
|
@ -412,11 +421,12 @@ test("configCustomFileSystemSync", (t) => {
|
||||||
return t.fail(p);
|
return t.fail(p);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const actual = markdownlint.readConfigSync(file, null, fsApi);
|
const actual = markdownlint.readConfigSync(file, undefined, fsApi);
|
||||||
const expected = {
|
const expected = {
|
||||||
...extendedContent,
|
...extendedContent,
|
||||||
...fileContent
|
...fileContent
|
||||||
};
|
};
|
||||||
|
// @ts-ignore
|
||||||
delete expected.extends;
|
delete expected.extends;
|
||||||
t.deepEqual(actual, expected, "Config object not correct.");
|
t.deepEqual(actual, expected, "Config object not correct.");
|
||||||
});
|
});
|
||||||
|
|
@ -479,12 +489,13 @@ test("configCustomFileSystemPromise", (t) => new Promise((resolve) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
markdownlint.promises.readConfig(file, null, fsApi)
|
markdownlint.promises.readConfig(file, undefined, fsApi)
|
||||||
.then((actual) => {
|
.then((actual) => {
|
||||||
const expected = {
|
const expected = {
|
||||||
...extendedContent,
|
...extendedContent,
|
||||||
...fileContent
|
...fileContent
|
||||||
};
|
};
|
||||||
|
// @ts-ignore
|
||||||
delete expected.extends;
|
delete expected.extends;
|
||||||
t.deepEqual(actual, expected, "Config object not correct.");
|
t.deepEqual(actual, expected, "Config object not correct.");
|
||||||
resolve();
|
resolve();
|
||||||
|
|
@ -503,3 +514,57 @@ test("configBadFilePromise", (t) => new Promise((resolve) => {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
test("extendSinglePromise", (t) => new Promise((resolve) => {
|
||||||
|
t.plan(1);
|
||||||
|
const expected = require("./config/config-child.json");
|
||||||
|
markdownlint.promises.extendConfig(
|
||||||
|
expected, "./test/config/config-child.json"
|
||||||
|
)
|
||||||
|
.then((actual) => {
|
||||||
|
t.deepEqual(actual, expected, "Config object not correct.");
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
test("extendCustomFileSystemPromise", (t) => new Promise((resolve) => {
|
||||||
|
t.plan(4);
|
||||||
|
const file = path.resolve("/dir/file.json");
|
||||||
|
const extended = path.resolve("/dir/extended.json");
|
||||||
|
const fileContent = {
|
||||||
|
"extends": extended,
|
||||||
|
"default": true,
|
||||||
|
"MD001": false
|
||||||
|
};
|
||||||
|
const extendedContent = {
|
||||||
|
"MD001": true,
|
||||||
|
"MD002": true
|
||||||
|
};
|
||||||
|
const fsApi = {
|
||||||
|
"access": (p, m, cb) => {
|
||||||
|
t.is(p, extended);
|
||||||
|
return (cb || m)();
|
||||||
|
},
|
||||||
|
"readFile": (p, o, cb) => {
|
||||||
|
switch (p) {
|
||||||
|
case extended:
|
||||||
|
t.is(p, extended);
|
||||||
|
return cb(null, JSON.stringify(extendedContent));
|
||||||
|
default:
|
||||||
|
return t.fail();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
markdownlint.promises.extendConfig(fileContent, file, undefined, fsApi)
|
||||||
|
.then((actual) => {
|
||||||
|
t.truthy(fileContent.extends);
|
||||||
|
const expected = {
|
||||||
|
...extendedContent,
|
||||||
|
...fileContent
|
||||||
|
};
|
||||||
|
// @ts-ignore
|
||||||
|
delete expected.extends;
|
||||||
|
t.deepEqual(actual, expected, "Config object not correct.");
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue