Socket
Socket
Sign inDemoInstall

bpmn-js-bpmnlint

Package Overview
Dependencies
Maintainers
2
Versions
43
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

bpmn-js-bpmnlint - npm Package Compare versions

Comparing version 0.10.1 to 0.11.0

karma.conf.js

7

CHANGELOG.md

@@ -9,2 +9,9 @@ # Changelog

## 0.11.0
* `FEAT`: integrate with `editorActions`
* `FEAT`: show human readable error on missing `config.linting`
* `CHORE`: test against `bpmn-js@4`
* `CHORE`: test against `bpmnlint@5.1`
## 0.10.1

@@ -11,0 +18,0 @@

455

dist/index.esm.js

@@ -1,420 +0,5 @@

import { assign, groupBy, reduce } from 'min-dash';
import { Linter } from 'bpmnlint';
import { reduce, groupBy, assign } from 'min-dash';
import { domify, query, remove } from 'min-dom';
/**
* Traverse a moddle tree, depth first from top to bottom
* and call the passed visitor fn.
*
* @param {ModdleElement} element
* @param {Function} fn
*/
var traverse = function traverse(element, fn) {
fn(element);
var descriptor = element.$descriptor;
if (descriptor.isGeneric) {
return;
}
var containedProperties = descriptor.properties.filter(p => {
return !p.isAttr && !p.isReference && p.type !== 'String';
});
containedProperties.forEach(p => {
if (p.name in element) {
const propertyValue = element[p.name];
if (p.isMany) {
propertyValue.forEach(child => {
traverse(child, fn);
});
} else {
traverse(propertyValue, fn);
}
}
});
};
class Reporter {
constructor({ moddleRoot, rule }) {
this.rule = rule;
this.moddleRoot = moddleRoot;
this.messages = [];
this.report = this.report.bind(this);
}
report(id, message) {
this.messages.push({ id, message });
}
}
var testRule = function testRule({ moddleRoot, rule }) {
const reporter = new Reporter({ rule, moddleRoot });
traverse(moddleRoot, node => rule.check(node, reporter));
return reporter.messages;
};
const categoryMap = {
0: 'off',
1: 'warn',
2: 'error'
};
function Linter(options = {}) {
const {
config,
resolver
} = options;
if (typeof resolver === 'undefined') {
throw new Error('must provide <options.resolver>');
}
this.config = config;
this.resolver = resolver;
this.cachedRules = {};
this.cachedConfigs = {};
}
var linter = Linter;
/**
* Applies a rule on the moddleRoot and adds reports to the finalReport
*
* @param {ModdleElement} moddleRoot
*
* @param {Object} ruleDefinition.name
* @param {Object} ruleDefinition.config
* @param {Object} ruleDefinition.category
* @param {Rule} ruleDefinition.rule
*
* @return {Array<ValidationErrors>} rule reports
*/
Linter.prototype.applyRule = function applyRule(moddleRoot, ruleDefinition) {
const {
config,
rule,
category,
name
} = ruleDefinition;
try {
const reports = testRule({
moddleRoot,
rule,
config
});
return reports.map(function(report) {
return {
...report,
category
};
});
} catch (e) {
console.error('rule <' + name + '> failed with error: ', e);
return [
{
message: 'Rule error: ' + e.message,
category: 'error'
}
];
}
};
Linter.prototype.resolveRule = function(name) {
const {
pkg,
ruleName
} = this.parseRuleName(name);
const id = `${pkg}-${ruleName}`;
const rule = this.cachedRules[id];
if (rule) {
return Promise.resolve(rule);
}
return Promise.resolve(this.resolver.resolveRule(pkg, ruleName)).then((ruleFactory) => {
if (!ruleFactory) {
throw new Error(`unknown rule <${name}>`);
}
const rule = this.cachedRules[id] = ruleFactory();
return rule;
});
};
Linter.prototype.resolveConfig = function(name) {
const {
pkg,
configName
} = this.parseConfigName(name);
const id = `${pkg}-${configName}`;
const config = this.cachedConfigs[id];
if (config) {
return Promise.resolve(config);
}
return Promise.resolve(this.resolver.resolveConfig(pkg, configName)).then((config) => {
if (!config) {
throw new Error(`unknown config <${name}>`);
}
const actualConfig = this.cachedConfigs[id] = normalizeConfig(config, pkg);
return actualConfig;
});
};
/**
* Take a linter config and return list of resolved rules.
*
* @param {Object} config
*
* @return {Array<RuleDefinition>}
*/
Linter.prototype.resolveRules = function(config) {
return this.resolveConfiguredRules(config).then((rulesConfig) => {
// parse rule values
const parsedRules = Object.entries(rulesConfig).map(([ name, value ]) => {
const {
category,
config
} = this.parseRuleValue(value);
return {
name,
category,
config
};
});
// filter only for enabled rules
const enabledRules = parsedRules.filter(definition => definition.category !== 'off');
// load enabled rules
const loaders = enabledRules.map((definition) => {
const {
name
} = definition;
return this.resolveRule(name).then(function(rule) {
return {
...definition,
rule
};
});
});
return Promise.all(loaders);
});
};
Linter.prototype.resolveConfiguredRules = function(config) {
let parents = config.extends;
if (typeof parents === 'string') {
parents = [ parents ];
}
if (typeof parents === 'undefined') {
parents = [];
}
return Promise.all(
parents.map((configName) => {
return this.resolveConfig(configName).then((config) => {
return this.resolveConfiguredRules(config);
});
})
).then((inheritedRules) => {
const overrideRules = normalizeConfig(config, 'bpmnlint').rules;
const rules = [ ...inheritedRules, overrideRules ].reduce((rules, currentRules) => {
return {
...rules,
...currentRules
};
}, {});
return rules;
});
};
/**
* Lint the given model root, using the specified linter config.
*
* @param {ModdleElement} moddleRoot
* @param {Object} [config] the bpmnlint configuration to use
*
* @return {Object} lint results, keyed by category names
*/
Linter.prototype.lint = function(moddleRoot, config) {
config = config || this.config;
// load rules
return this.resolveRules(config).then((ruleDefinitions) => {
const allReports = {};
ruleDefinitions.forEach((ruleDefinition) => {
const {
name
} = ruleDefinition;
const reports = this.applyRule(moddleRoot, ruleDefinition);
if (reports.length) {
allReports[name] = reports;
}
});
return allReports;
});
};
Linter.prototype.parseRuleValue = function(value) {
let category;
let config;
if (Array.isArray(value)) {
category = value[0];
config = value[1];
} else {
category = value;
config = {};
}
// normalize rule flag to <error> and <warn> which
// may be upper case or a number at this point
if (typeof category === 'string') {
category = category.toLowerCase();
}
category = categoryMap[category] || category;
return {
config,
category
};
};
Linter.prototype.parseRuleName = function(name) {
const slashIdx = name.indexOf('/');
// resolve rule as built-in, if unprefixed
if (slashIdx === -1) {
return {
pkg: 'bpmnlint',
ruleName: name
};
}
const pkg = name.substring(0, slashIdx);
const ruleName = name.substring(slashIdx + 1);
if (pkg === 'bpmnlint') {
return {
pkg: 'bpmnlint',
ruleName
};
} else {
return {
pkg: 'bpmnlint-plugin-' + pkg,
ruleName
};
}
};
Linter.prototype.parseConfigName = function(name) {
const localMatch = /^bpmnlint:(.*)$/.exec(name);
if (localMatch) {
return {
pkg: 'bpmnlint',
configName: localMatch[1]
};
}
const pluginMatch = /^plugin:([^/]+)\/(.+)$/.exec(name);
if (!pluginMatch) {
throw new Error(`invalid config name <${ name }>`);
}
return {
pkg: 'bpmnlint-plugin-' + pluginMatch[1],
configName: pluginMatch[2]
};
};
// helpers ///////////////////////////
/**
* Validate and return validated config.
*
* @param {Object} config
* @param {String} pkg
*
* @return {Object} validated config
*/
function normalizeConfig(config, pkg) {
const rules = config.rules || {};
const validatedRules = Object.keys(rules).reduce((normalizedRules, name) => {
const value = rules[name];
// prefix local rule definition
if (name.indexOf('bpmnlint/') === 0) {
name = name.substring('bpmnlint/'.length);
}
normalizedRules[name] = value;
return normalizedRules;
}, {});
return {
...config,
rules: validatedRules
};
}
var ErrorSvg = "<svg width=\"12\" height=\"12\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 352 512\"><path fill=\"currentColor\" d=\"M242.72 256l100.07-100.07c12.28-12.28 12.28-32.19 0-44.48l-22.24-22.24c-12.28-12.28-32.19-12.28-44.48 0L176 189.28 75.93 89.21c-12.28-12.28-32.19-12.28-44.48 0L9.21 111.45c-12.28 12.28-12.28 32.19 0 44.48L109.28 256 9.21 356.07c-12.28 12.28-12.28 32.19 0 44.48l22.24 22.24c12.28 12.28 32.2 12.28 44.48 0L176 322.72l100.07 100.07c12.28 12.28 32.2 12.28 44.48 0l22.24-22.24c12.28-12.28 12.28-32.19 0-44.48L242.72 256z\"></path></svg>";

@@ -446,2 +31,6 @@

if (!config) {
throw new Error('missing required linting option');
}
if ('bpmnlint' in config) {

@@ -571,3 +160,3 @@ this._linterConfig = config.bpmnlint;

var remove$$1 = {},
var remove = {},
update = {},

@@ -578,3 +167,3 @@ add = {};

if (!newIssues[id]) {
remove$$1[id] = self._issues[id];
remove[id] = self._issues[id];
}

@@ -593,3 +182,3 @@ }

remove$$1 = assign(remove$$1, update);
remove = assign(remove, update);
add = assign(add, update);

@@ -599,3 +188,3 @@

self.removeIssues(remove$$1);
self.removeIssues(remove);
self.createIssues(add);

@@ -818,5 +407,5 @@

var linter$$1 = new linter(this._linterConfig);
var linter = new Linter(this._linterConfig);
return linter$$1.lint(definitions);
return linter.lint(definitions);
};

@@ -833,5 +422,21 @@

function EditorActions(injector, linting) {
var editorActions = injector.get('editorActions', false);
editorActions && editorActions.register({
toggleLinting: function() {
linting.toggleLinting();
}
});
}
EditorActions.$inject = [
'injector',
'linting'
];
var index = {
__init__: [ 'linting' ],
linting: [ 'type', Linting ]
__init__: [ 'linting', 'lintingEditorActions' ],
linting: [ 'type', Linting ],
lintingEditorActions: ['type', EditorActions]
};

@@ -838,0 +443,0 @@

'use strict';
var bpmnlint = require('bpmnlint');
var minDash = require('min-dash');
var minDom = require('min-dom');
/**
* Traverse a moddle tree, depth first from top to bottom
* and call the passed visitor fn.
*
* @param {ModdleElement} element
* @param {Function} fn
*/
var traverse = function traverse(element, fn) {
fn(element);
var descriptor = element.$descriptor;
if (descriptor.isGeneric) {
return;
}
var containedProperties = descriptor.properties.filter(p => {
return !p.isAttr && !p.isReference && p.type !== 'String';
});
containedProperties.forEach(p => {
if (p.name in element) {
const propertyValue = element[p.name];
if (p.isMany) {
propertyValue.forEach(child => {
traverse(child, fn);
});
} else {
traverse(propertyValue, fn);
}
}
});
};
class Reporter {
constructor({ moddleRoot, rule }) {
this.rule = rule;
this.moddleRoot = moddleRoot;
this.messages = [];
this.report = this.report.bind(this);
}
report(id, message) {
this.messages.push({ id, message });
}
}
var testRule = function testRule({ moddleRoot, rule }) {
const reporter = new Reporter({ rule, moddleRoot });
traverse(moddleRoot, node => rule.check(node, reporter));
return reporter.messages;
};
const categoryMap = {
0: 'off',
1: 'warn',
2: 'error'
};
function Linter(options = {}) {
const {
config,
resolver
} = options;
if (typeof resolver === 'undefined') {
throw new Error('must provide <options.resolver>');
}
this.config = config;
this.resolver = resolver;
this.cachedRules = {};
this.cachedConfigs = {};
}
var linter = Linter;
/**
* Applies a rule on the moddleRoot and adds reports to the finalReport
*
* @param {ModdleElement} moddleRoot
*
* @param {Object} ruleDefinition.name
* @param {Object} ruleDefinition.config
* @param {Object} ruleDefinition.category
* @param {Rule} ruleDefinition.rule
*
* @return {Array<ValidationErrors>} rule reports
*/
Linter.prototype.applyRule = function applyRule(moddleRoot, ruleDefinition) {
const {
config,
rule,
category,
name
} = ruleDefinition;
try {
const reports = testRule({
moddleRoot,
rule,
config
});
return reports.map(function(report) {
return {
...report,
category
};
});
} catch (e) {
console.error('rule <' + name + '> failed with error: ', e);
return [
{
message: 'Rule error: ' + e.message,
category: 'error'
}
];
}
};
Linter.prototype.resolveRule = function(name) {
const {
pkg,
ruleName
} = this.parseRuleName(name);
const id = `${pkg}-${ruleName}`;
const rule = this.cachedRules[id];
if (rule) {
return Promise.resolve(rule);
}
return Promise.resolve(this.resolver.resolveRule(pkg, ruleName)).then((ruleFactory) => {
if (!ruleFactory) {
throw new Error(`unknown rule <${name}>`);
}
const rule = this.cachedRules[id] = ruleFactory();
return rule;
});
};
Linter.prototype.resolveConfig = function(name) {
const {
pkg,
configName
} = this.parseConfigName(name);
const id = `${pkg}-${configName}`;
const config = this.cachedConfigs[id];
if (config) {
return Promise.resolve(config);
}
return Promise.resolve(this.resolver.resolveConfig(pkg, configName)).then((config) => {
if (!config) {
throw new Error(`unknown config <${name}>`);
}
const actualConfig = this.cachedConfigs[id] = normalizeConfig(config, pkg);
return actualConfig;
});
};
/**
* Take a linter config and return list of resolved rules.
*
* @param {Object} config
*
* @return {Array<RuleDefinition>}
*/
Linter.prototype.resolveRules = function(config) {
return this.resolveConfiguredRules(config).then((rulesConfig) => {
// parse rule values
const parsedRules = Object.entries(rulesConfig).map(([ name, value ]) => {
const {
category,
config
} = this.parseRuleValue(value);
return {
name,
category,
config
};
});
// filter only for enabled rules
const enabledRules = parsedRules.filter(definition => definition.category !== 'off');
// load enabled rules
const loaders = enabledRules.map((definition) => {
const {
name
} = definition;
return this.resolveRule(name).then(function(rule) {
return {
...definition,
rule
};
});
});
return Promise.all(loaders);
});
};
Linter.prototype.resolveConfiguredRules = function(config) {
let parents = config.extends;
if (typeof parents === 'string') {
parents = [ parents ];
}
if (typeof parents === 'undefined') {
parents = [];
}
return Promise.all(
parents.map((configName) => {
return this.resolveConfig(configName).then((config) => {
return this.resolveConfiguredRules(config);
});
})
).then((inheritedRules) => {
const overrideRules = normalizeConfig(config, 'bpmnlint').rules;
const rules = [ ...inheritedRules, overrideRules ].reduce((rules, currentRules) => {
return {
...rules,
...currentRules
};
}, {});
return rules;
});
};
/**
* Lint the given model root, using the specified linter config.
*
* @param {ModdleElement} moddleRoot
* @param {Object} [config] the bpmnlint configuration to use
*
* @return {Object} lint results, keyed by category names
*/
Linter.prototype.lint = function(moddleRoot, config) {
config = config || this.config;
// load rules
return this.resolveRules(config).then((ruleDefinitions) => {
const allReports = {};
ruleDefinitions.forEach((ruleDefinition) => {
const {
name
} = ruleDefinition;
const reports = this.applyRule(moddleRoot, ruleDefinition);
if (reports.length) {
allReports[name] = reports;
}
});
return allReports;
});
};
Linter.prototype.parseRuleValue = function(value) {
let category;
let config;
if (Array.isArray(value)) {
category = value[0];
config = value[1];
} else {
category = value;
config = {};
}
// normalize rule flag to <error> and <warn> which
// may be upper case or a number at this point
if (typeof category === 'string') {
category = category.toLowerCase();
}
category = categoryMap[category] || category;
return {
config,
category
};
};
Linter.prototype.parseRuleName = function(name) {
const slashIdx = name.indexOf('/');
// resolve rule as built-in, if unprefixed
if (slashIdx === -1) {
return {
pkg: 'bpmnlint',
ruleName: name
};
}
const pkg = name.substring(0, slashIdx);
const ruleName = name.substring(slashIdx + 1);
if (pkg === 'bpmnlint') {
return {
pkg: 'bpmnlint',
ruleName
};
} else {
return {
pkg: 'bpmnlint-plugin-' + pkg,
ruleName
};
}
};
Linter.prototype.parseConfigName = function(name) {
const localMatch = /^bpmnlint:(.*)$/.exec(name);
if (localMatch) {
return {
pkg: 'bpmnlint',
configName: localMatch[1]
};
}
const pluginMatch = /^plugin:([^/]+)\/(.+)$/.exec(name);
if (!pluginMatch) {
throw new Error(`invalid config name <${ name }>`);
}
return {
pkg: 'bpmnlint-plugin-' + pluginMatch[1],
configName: pluginMatch[2]
};
};
// helpers ///////////////////////////
/**
* Validate and return validated config.
*
* @param {Object} config
* @param {String} pkg
*
* @return {Object} validated config
*/
function normalizeConfig(config, pkg) {
const rules = config.rules || {};
const validatedRules = Object.keys(rules).reduce((normalizedRules, name) => {
const value = rules[name];
// prefix local rule definition
if (name.indexOf('bpmnlint/') === 0) {
name = name.substring('bpmnlint/'.length);
}
normalizedRules[name] = value;
return normalizedRules;
}, {});
return {
...config,
rules: validatedRules
};
}
var ErrorSvg = "<svg width=\"12\" height=\"12\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 352 512\"><path fill=\"currentColor\" d=\"M242.72 256l100.07-100.07c12.28-12.28 12.28-32.19 0-44.48l-22.24-22.24c-12.28-12.28-32.19-12.28-44.48 0L176 189.28 75.93 89.21c-12.28-12.28-32.19-12.28-44.48 0L9.21 111.45c-12.28 12.28-12.28 32.19 0 44.48L109.28 256 9.21 356.07c-12.28 12.28-12.28 32.19 0 44.48l22.24 22.24c12.28 12.28 32.2 12.28 44.48 0L176 322.72l100.07 100.07c12.28 12.28 32.2 12.28 44.48 0l22.24-22.24c12.28-12.28 12.28-32.19 0-44.48L242.72 256z\"></path></svg>";

@@ -448,2 +33,6 @@

if (!config) {
throw new Error('missing required linting option');
}
if ('bpmnlint' in config) {

@@ -816,5 +405,5 @@ this._linterConfig = config.bpmnlint;

var linter$$1 = new linter(this._linterConfig);
var linter = new bpmnlint.Linter(this._linterConfig);
return linter$$1.lint(definitions);
return linter.lint(definitions);
};

@@ -831,5 +420,21 @@

function EditorActions(injector, linting) {
var editorActions = injector.get('editorActions', false);
editorActions && editorActions.register({
toggleLinting: function() {
linting.toggleLinting();
}
});
}
EditorActions.$inject = [
'injector',
'linting'
];
var index = {
__init__: [ 'linting' ],
linting: [ 'type', Linting ]
__init__: [ 'linting', 'lintingEditorActions' ],
linting: [ 'type', Linting ],
lintingEditorActions: ['type', EditorActions]
};

@@ -836,0 +441,0 @@

{
"name": "bpmn-js-bpmnlint",
"version": "0.10.1",
"version": "0.11.0",
"description": "bpmn-js integration for bpmnlint",
"main": "dist/index.js",
"module": "dist/index.esm.js",
"source": "lib/index.js",
"scripts": {
"all": "run-s bundle copy-assets",
"all": "run-s test distro copy-assets",
"test": "karma start --no-auto-test --single-run",
"dev": "karma start",
"distro": "run-s bundle test:bundle",
"bundle": "NODE_ENV=production rollup -c",
"test:bundle": "echo \"NO TESTS YET\"",
"copy-assets": "cpx 'assets/css/*' dist/assets/css -v",

@@ -26,12 +31,22 @@ "prepublishOnly": "run-s bundle copy-assets"

"devDependencies": {
"bpmn-font": "^0.8.0",
"bpmn-js": "^2.4.1",
"bpmnlint": "^5.0.0",
"bpmn-js": "^4.0.3",
"bpmnlint": "^5.1.1",
"bpmnlint-loader": "^0.1.3",
"chai": "^4.2.0",
"cpx": "^1.5.0",
"karma": "^4.2.0",
"karma-chrome-launcher": "^3.0.0",
"karma-mocha": "^1.3.0",
"karma-sinon-chai": "^2.0.2",
"karma-webpack": "^4.0.2",
"mocha": "^6.2.0",
"mocha-test-container-support": "^0.2.0",
"npm-run-all": "^4.1.5",
"rollup": "^0.65.2",
"rollup-plugin-commonjs": "^9.1.6",
"rollup-plugin-json": "^3.0.0",
"rollup-plugin-node-resolve": "^3.4.0",
"rollup-plugin-string": "^2.0.2"
"puppeteer": "^1.19.0",
"raw-loader": "^1.0.0",
"rollup": "^1.17.0",
"rollup-plugin-string": "^3.0.0",
"sinon": "^7.3.2",
"sinon-chai": "^3.3.0",
"webpack": "^4.37.0"
},

@@ -38,0 +53,0 @@ "dependencies": {

# bpmn-js-bpmnlint
[![Build Status](https://travis-ci.com/bpmn-io/bpmn-js-bpmnlint.svg?branch=master)](https://travis-ci.com/bpmn-io/bpmn-js-bpmnlint)
Integrates [bpmnlint](https://github.com/bpmn-io/bpmnlint) into [bpmn-js](https://github.com/bpmn-io/bpmn-js).

@@ -55,3 +57,4 @@

```
npm install && npm run dev
npm install
npm run dev
```

@@ -58,0 +61,0 @@

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc