Repository: bpmn-io/bpmnlint (js)

Issue:
Be Able to Configure Rules
__Is your feature request related to a problem? Please describe__

Rules cannot be configured at the moment. In [eslint](https://eslint.org/docs/developer-guide/working-with-rules#the-context-object) this is possible allowing for the reuse of configurable rules.


__Describe the solution you'd like__

<!-- A clear and concise description of what you want to happen. -->

An example of a configuration:

```javascript
module.exports = {
  configs: {
    'foo': {
      rules: {
        'bar': [ 'error', {
          types: [ 'bpmn:ServiceTask' ]
        } ]
      }
    }
  }
};
```

__Describe alternatives you've considered__

<!-- A clear and concise description of any alternative solutions or features you've considered. -->
Alternatively, rules with different configurations can be created as separate files. However, this would not be my preferred solution.


Pull request description:
feat: pass configuration to rule factory
Configuration was already a feature. The only missing piece was passing the configuration to the rule factory.

Closes #78

<!--

Thanks for creating this pull request!

Please make sure to link the issue you are closing as "Closes #issueNr". 
This helps us to understand the context of this PR.

-->


Patch:
diff --git a/lib/linter.js b/lib/linter.js
index 8a546e3..2fdb883 100644
--- a/lib/linter.js
+++ b/lib/linter.js
@@ -77,7 +77,7 @@ Linter.prototype.applyRule = function applyRule(moddleRoot, ruleDefinition) {
 };
 
 
-Linter.prototype.resolveRule = function(name) {
+Linter.prototype.resolveRule = function(name, config) {
 
   const {
     pkg,
@@ -98,7 +98,7 @@ Linter.prototype.resolveRule = function(name) {
       throw new Error(`unknown rule <${name}>`);
     }
 
-    const rule = this.cachedRules[id] = ruleFactory();
+    const rule = this.cachedRules[id] = ruleFactory(config);
 
     return rule;
   });
@@ -163,10 +163,11 @@ Linter.prototype.resolveRules = function(config) {
     const loaders = enabledRules.map((definition) => {
 
       const {
-        name
+        name,
+        config
       } = definition;
 
-      return this.resolveRule(name).then(function(rule) {
+      return this.resolveRule(name, config).then(function(rule) {
         return {
           ...definition,
           rule


Test patch:
diff --git a/test/spec/linter-spec.js b/test/spec/linter-spec.js
index c19cf2f..168b177 100644
--- a/test/spec/linter-spec.js
+++ b/test/spec/linter-spec.js
@@ -220,6 +220,35 @@ describe('linter', function() {
       });
 
 
+      it('should resolve and configure', async function() {
+
+        // given
+        const resolver = {
+          resolveRule(pkg, ruleName) {
+            expect(pkg).to.eql('bpmnlint');
+
+            expect(ruleName).to.eql('testRule');
+
+            return fakeRule;
+          }
+        };
+
+        const linter = new Linter({ resolver });
+
+        // when
+        const lintResults = await linter.lint(moddleRoot, {
+          rules: {
+            testRule: [ 'error', { message: 'foo' } ]
+          }
+        });
+
+        // then
+        expect(lintResults).to.eql({
+          testRule: buildFakeResults('error', 'foo')
+        });
+      });
+
+
       it('should resolve async', async function() {
 
         // given
@@ -901,12 +930,13 @@ async function fakeAsyncRule() {
   };
 }
 
-function fakeRule() {
+function fakeRule(config = {}) {
+  const { message } = config;
 
   function check(node, reporter) {
 
     if (is(node, 'Definitions')) {
-      reporter.report(node.id, 'Definitions detected');
+      reporter.report(node.id, message || 'Definitions detected');
     }
   }
 
@@ -916,11 +946,11 @@ function fakeRule() {
 }
 
 
-function buildFakeResults(category) {
+function buildFakeResults(category, message) {
   const results = [
     {
       id: 'sid-38422fae-e03e-43a3-bef4-bd33b32041b2',
-      message: 'Definitions detected'
+      message: message || 'Definitions detected'
     }
   ];