custom icons in diagram definition

This commit is contained in:
Klemek
2019-07-16 15:03:35 +02:00
parent aaa13a3732
commit ed8ddd349d
3 changed files with 104 additions and 23 deletions
+11 -2
View File
@@ -193,7 +193,7 @@ Array of object as following:
| Key | Type | Required | Info | | Key | Type | Required | Info |
| --- | --- | --- | --- | | --- | --- | --- | --- |
| **`name`** | string | **yes** | used in links to reference nodes | | **`name`** | string | **yes** | used in links to reference nodes |
| **`icon`** | string | **yes** | name of the Font-Awesome icon of the node (see [Icon names](#icon-names)) | | **`icon`** | string/object | **yes** | name of the Font-Awesome icon of the node (see [Icon names](#icon-names)) |
| `top`, `bottom`, `left`, `right` | string or object | no | see [Sub-elements](#sub-elements) | | `top`, `bottom`, `left`, `right` | string or object | no | see [Sub-elements](#sub-elements) |
| `color` | string | no | redefined the color | | `color` | string | no | redefined the color |
| `scale` | number | no | redefine this node icon scale | | `scale` | number | no | redefine this node icon scale |
@@ -236,7 +236,7 @@ You can define a relative icon with the following:
| Key | Type | Required | Info | | Key | Type | Required | Info |
| --- | --- | --- | --- | | --- | --- | --- | --- |
| **`icon`** | string | **yes** | name of the Font-Awesome icon of the sub-element (see [Icon names](#icon-names)) | | **`icon`** | string/object | **yes** | name of the Font-Awesome icon of the sub-element (see [Icon names](#icon-names)) |
| `color` | string | no | redefine the color | | `color` | string | no | redefine the color |
| `scale` | number | no | redefine this icon scale | | `scale` | number | no | redefine this icon scale |
@@ -250,6 +250,15 @@ When you reference an icon, for example `circle`, it's searched in the `solid` f
If, in this case you want the hollow circle from the regular style, just enter `regular circle` or `circle regular` instead. If, in this case you want the hollow circle from the regular style, just enter `regular circle` or `circle regular` instead.
It's very flexible as you can copy-paste from an HTML page `far fa-circle` and it will also works. It's very flexible as you can copy-paste from an HTML page `far fa-circle` and it will also works.
You can also specify a custom icon by entering the following object instead of a string:
| Key | Type | Required | Info |
| --- | --- | --- | --- |
| **`path`** | string | **yes** | the SVG path of your icon |
| `width` | string | no | the custom width of the path (if blank, height is taken, then the height of all icons: 512) |
| `height` | string | no | the custom height of the path (if blank, width is taken) |
### Link types ### Link types
Here are the accepted types and their preview : Here are the accepted types and their preview :
+33 -13
View File
@@ -25,7 +25,7 @@ try {
* @property {string} name * @property {string} name
* @property {number} x * @property {number} x
* @property {number} y * @property {number} y
* @property {string} icon * @property {string|{path:string,width:number:height:number}} icon
*/ */
/** /**
@@ -38,7 +38,12 @@ try {
const SUB_DEF = { const SUB_DEF = {
'_': 'string', '_': 'string',
'text': 'string', 'text': 'string',
'icon': 'string', 'icon': {
'_': 'string',
'path': 'string',
'width': 'number',
'height': 'number'
},
'color': 'string', 'color': 'string',
'font': 'string', 'font': 'string',
'font-size': 'number', 'font-size': 'number',
@@ -48,7 +53,12 @@ const SUB_DEF = {
const NODE_DEF = { const NODE_DEF = {
'name': '!string', 'name': '!string',
'icon': '!string', 'icon': {
'_': 'string',
'path': 'string',
'width': 'number',
'height': 'number'
},
'x': '!number', 'x': '!number',
'y': '!number', 'y': '!number',
'color': 'string', 'color': 'string',
@@ -110,16 +120,25 @@ module.exports = (options) => {
const self = { const self = {
/** /**
* Find icon data from given name * Find icon data from given name or data
* @param {string} name * @param {string|{path: string, width: number, height: number}} icon
* @returns {null|{path: string, width: number}} * @returns {null|{path: string, width: number, height: number}}
*/ */
getIcon: (name) => { getIcon: (icon) => {
if (!name || !name.trim()) if (!icon)
return null;
if (typeof icon === 'object') {
icon.height = icon.height || icon.width || resources.height;
icon.width = icon.width || icon.height;
return icon;
}
if (!icon.trim())
return null; return null;
let search = utils.ezClone(resources.index); let search = utils.ezClone(resources.index);
const spl = name.trim().split(' ').map(t => t.indexOf('fa-') === 0 ? t.substr(3) : t); const spl = icon.trim().split(' ').map(t => t.indexOf('fa-') === 0 ? t.substr(3) : t);
for (let i = 0; i < spl.length; i++) { for (let i = 0; i < spl.length; i++) {
//replace fas by regular for example //replace fas by regular for example
@@ -131,11 +150,12 @@ module.exports = (options) => {
} }
} }
name = spl[0]; icon = spl[0];
for (let i = 0; i < search.length; i++) { for (let i = 0; i < search.length; i++) {
if (resources.icons[search[i]] && resources.icons[search[i]][name]) { if (resources.icons[search[i]] && resources.icons[search[i]][icon]) {
return resources.icons[search[i]][name]; resources.icons[search[i]][icon].height = resources.height;
return resources.icons[search[i]][icon];
} }
} }
@@ -216,7 +236,7 @@ module.exports = (options) => {
}, },
'g': { 'g': {
'_attributes': { '_attributes': {
'transform': `scale(${scale / resources.height} ${scale / resources.height}) translate(${-icon.width / 2} ${-resources.height / 2})`, 'transform': `scale(${scale / icon.height} ${scale / icon.height}) translate(${-icon.width / 2} ${-icon.height / 2})`,
'stroke': (node['color'] || options['icons']['color'] || undefined), 'stroke': (node['color'] || options['icons']['color'] || undefined),
'fill': (node['color'] || options['icons']['color'] || undefined) 'fill': (node['color'] || options['icons']['color'] || undefined)
}, },
+60 -8
View File
@@ -61,56 +61,64 @@ describe('getIcon', () => {
const res = rendering().getIcon('circle'); const res = rendering().getIcon('circle');
expect(res).toEqual({ expect(res).toEqual({
path: solidCirclePath, path: solidCirclePath,
width: 512 width: 512,
height: 512
}); });
}); });
test('valid circle alt name', () => { test('valid circle alt name', () => {
const res = rendering().getIcon('fa-circle'); const res = rendering().getIcon('fa-circle');
expect(res).toEqual({ expect(res).toEqual({
path: solidCirclePath, path: solidCirclePath,
width: 512 width: 512,
height: 512
}); });
}); });
test('ignored other name', () => { test('ignored other name', () => {
const res = rendering().getIcon('circle server'); const res = rendering().getIcon('circle server');
expect(res).toEqual({ expect(res).toEqual({
path: solidCirclePath, path: solidCirclePath,
width: 512 width: 512,
height: 512
}); });
}); });
test('forcing regular', () => { test('forcing regular', () => {
const res = rendering().getIcon('far circle'); const res = rendering().getIcon('far circle');
expect(res).toEqual({ expect(res).toEqual({
path: regularCirclePath, path: regularCirclePath,
width: 512 width: 512,
height: 512
}); });
}); });
test('forcing regular 2', () => { test('forcing regular 2', () => {
const res = rendering().getIcon('regular circle'); const res = rendering().getIcon('regular circle');
expect(res).toEqual({ expect(res).toEqual({
path: regularCirclePath, path: regularCirclePath,
width: 512 width: 512,
height: 512
}); });
}); });
test('forcing regular 3', () => { test('forcing regular 3', () => {
const res = rendering().getIcon('circle far'); const res = rendering().getIcon('circle far');
expect(res).toEqual({ expect(res).toEqual({
path: regularCirclePath, path: regularCirclePath,
width: 512 width: 512,
height: 512
}); });
}); });
test('double type', () => { test('double type', () => {
const res = rendering().getIcon('circle far solid'); const res = rendering().getIcon('circle far solid');
expect(res).toEqual({ expect(res).toEqual({
path: regularCirclePath, path: regularCirclePath,
width: 512 width: 512,
height: 512
}); });
}); });
test('double type 2', () => { test('double type 2', () => {
const res = rendering().getIcon('circle solid far'); const res = rendering().getIcon('circle solid far');
expect(res).toEqual({ expect(res).toEqual({
path: solidCirclePath, path: solidCirclePath,
width: 512 width: 512,
height: 512
}); });
}); });
test('forcing solid on brands icon', () => { test('forcing solid on brands icon', () => {
@@ -119,6 +127,50 @@ describe('getIcon', () => {
const res2 = rendering().getIcon('fas usb'); const res2 = rendering().getIcon('fas usb');
expect(res2).toBeNull(); expect(res2).toBeNull();
}); });
test('custom icon 1', () => {
const res = rendering().getIcon({
path: 'hello',
width: 80,
height: 160
});
expect(res).toEqual({
path: 'hello',
width: 80,
height: 160
});
});
test('custom icon 2', () => {
const res = rendering().getIcon({
path: 'hello',
width: 80
});
expect(res).toEqual({
path: 'hello',
width: 80,
height: 80
});
});
test('custom icon 3', () => {
const res = rendering().getIcon({
path: 'hello',
height: 160
});
expect(res).toEqual({
path: 'hello',
width: 160,
height: 160
});
});
test('custom icon 4', () => {
const res = rendering().getIcon({
path: 'hello'
});
expect(res).toEqual({
path: 'hello',
width: 512,
height: 512
});
});
}); });
describe('getLinkPath (non-regression)', () => { describe('getLinkPath (non-regression)', () => {