...
 
Commits (9)
# html-validate changelog
# [2.2.0](https://gitlab.com/html-validate/html-validate/compare/v2.1.0...v2.2.0) (2019-11-23)
### Bug Fixes
- **config:** throw ConfigError when elements cannot be loaded ([62c08e7](https://gitlab.com/html-validate/html-validate/commit/62c08e7c8bf9deaa47f8b9f1afbf48dcc69bba32))
- **docs:** update plugin docs ([340d0ca](https://gitlab.com/html-validate/html-validate/commit/340d0ca23875331b4267a7fd0226532904ed8fda))
- **plugin:** make all fields optional ([a587239](https://gitlab.com/html-validate/html-validate/commit/a5872397a9a0732a4cea1901c65e024767809d4a))
### Features
- **plugin:** allow specifying name ([6554f72](https://gitlab.com/html-validate/html-validate/commit/6554f72fb11e2da59ab07774f0898b20654e2a5b))
# [2.1.0](https://gitlab.com/html-validate/html-validate/compare/v2.0.1...v2.1.0) (2019-11-21)
### Bug Fixes
......
......@@ -12,9 +12,16 @@ export interface Plugin {
/**
* Name of the plugin.
*
* Read-only property set by config.
* If specified this is the name used when referring to the plugin. Default is
* to use the name/path the user used when loading the plugin. To be less
* confusing for users you should use the same name as your package.
*
* The name must be a valid package name according to NPM (basically lowercase
* characters, must not begin with dot, slash or non-url safe characters).
*
* Hint: import and use the name from `package.json`.
*/
name: string;
name?: string;
/**
* Initialization callback.
......@@ -43,12 +50,12 @@ export interface Plugin {
*
* "extends": ["my-plugin:foobar"]
*/
configs: { [key: string]: ConfigData };
configs?: { [key: string]: ConfigData };
/**
* List of new rules present.
*/
rules: { [key: string]: RuleConstructor };
rules?: { [key: string]: RuleConstructor };
/**
* Transformer available in this plugin.
......@@ -72,7 +79,7 @@ export interface Plugin {
* "^.*\\.foo$": "my-plugin:foobar"
* }
*/
transformer: Transformer | Record<string, Transformer>;
transformer?: Transformer | Record<string, Transformer>;
/**
* Extend metadata validation schema.
......
This diff is collapsed.
......@@ -4,11 +4,12 @@ import { Source } from "../context";
import { UserError } from "../error/user-error";
import { Transformer, TRANSFORMER_API } from "../transform";
import { Config } from "./config";
import { ConfigError } from "./error";
import { Severity } from "./severity";
let mockElements: any;
jest.mock("mock-elements", () => mockElements, { virtual: true });
jest.mock("mock-plugin", () => ({ name: "mock plugin" }), { virtual: true });
jest.mock("mock-plugin", () => ({}), { virtual: true });
/* a mocked file which throws an exception when loaded */
jest.mock(
......@@ -316,6 +317,16 @@ describe("config", () => {
const metatable = config.getMetaTable();
expect(Object.keys(metatable.elements)).not.toHaveLength(0);
});
it("should throw ConfigError when module doesn't exist", () => {
const config = Config.fromObject({
elements: ["missing-module"],
});
expect(() => config.getMetaTable()).toThrow(ConfigError);
expect(() => config.getMetaTable()).toThrow(
/Failed to load elements from "missing-module": .*/
);
});
});
describe("transformSource()", () => {
......
......@@ -231,8 +231,15 @@ export class Config {
}
/* assume it is loadable with require() */
// eslint-disable-next-line security/detect-non-literal-require
metaTable.loadFromObject(require(entry));
try {
// eslint-disable-next-line security/detect-non-literal-require
metaTable.loadFromObject(require(entry));
} catch (err) {
throw new ConfigError(
`Failed to load elements from "${entry}": ${err.message}`,
err
);
}
}
metaTable.init();
......@@ -300,7 +307,7 @@ export class Config {
"<rootDir>",
this.rootDir
)) as Plugin;
plugin.name = moduleName;
plugin.name = plugin.name || moduleName;
return plugin;
});
}
......
......@@ -27,6 +27,56 @@ describe("Plugin", () => {
mockPlugin = require("mock-plugin");
});
describe("name", () => {
it("should use plugin name if set", () => {
expect.assertions(1);
mockPlugin.name = "my-plugin";
mockPlugin.configs = {
foo: {
rules: {
"my-rule": "error",
},
},
};
config = Config.fromObject({
extends: ["my-plugin:foo"],
plugins: ["mock-plugin"],
});
expect(config.get()).toEqual({
extends: ["my-plugin:foo"],
plugins: ["mock-plugin"],
rules: {
"my-rule": "error",
},
transform: {},
});
});
it("should default to package name", () => {
expect.assertions(1);
mockPlugin.name = null;
mockPlugin.configs = {
foo: {
rules: {
"my-rule": "error",
},
},
};
config = Config.fromObject({
extends: ["mock-plugin:foo"],
plugins: ["mock-plugin"],
});
expect(config.get()).toEqual({
extends: ["mock-plugin:foo"],
plugins: ["mock-plugin"],
rules: {
"my-rule": "error",
},
transform: {},
});
});
});
describe("configs", () => {
it("should add extendable predefined configurations", () => {
mockPlugin.configs = {
......
......@@ -13,9 +13,16 @@ export interface Plugin {
/**
* Name of the plugin.
*
* Read-only property set by config.
* If specified this is the name used when referring to the plugin. Default is
* to use the name/path the user used when loading the plugin. To be less
* confusing for users you should use the same name as your package.
*
* The name must be a valid package name according to NPM (basically lowercase
* characters, must not begin with dot, slash or non-url safe characters).
*
* Hint: import and use the name from `package.json`.
*/
name: string;
name?: string;
/**
* Initialization callback.
......@@ -44,12 +51,12 @@ export interface Plugin {
*
* "extends": ["my-plugin:foobar"]
*/
configs: { [key: string]: ConfigData };
configs?: Record<string, ConfigData>;
/**
* List of new rules present.
*/
rules: { [key: string]: RuleConstructor };
rules?: Record<string, RuleConstructor>;
/**
* Transformer available in this plugin.
......