673 lines
15 KiB
Markdown
673 lines
15 KiB
Markdown
[](https://www.npmjs.com/package/fa-diagrams)
|
|
[](https://travis-ci.org/Klemek/fa-diagrams)
|
|
[](https://github.com/boyter/scc/#badges-beta)
|
|
[](https://coveralls.io/github/Klemek/fa-diagrams?branch=master)
|
|
[](https://lgtm.com/projects/g/Klemek/fa-diagrams/context:javascript)
|
|
[](https://lgtm.com/projects/g/Klemek/fa-diagrams/alerts/)
|
|
|
|
# fa-diagrams
|
|
**SVG diagrams built from Font-Awesome icons**
|
|
|
|

|
|
|
|
### **[Web Editor](https://klemek.github.io/fa-diagrams)**
|
|
|
|
## Summary
|
|
|
|
* [Usage](#usage)
|
|
* [Node module](#node-module)
|
|
* [Html script](#html-script)
|
|
* [Install](#install)
|
|
* [CDN](#cdn)
|
|
* [Static scripts](#static-scripts)
|
|
* [NPM](#npm)
|
|
* [Build from sources](#build-from-sources)
|
|
* [API](#api)
|
|
* [`options`](#options)
|
|
* [`nodes`](#nodes)
|
|
* [`links`](#links)
|
|
* [Sub-elements](#sub-elements)
|
|
* [More info](#more-info)
|
|
* [Icon names](#icon-names)
|
|
* [Link types](#link-types)
|
|
* [Thrown errors](#thrown-errors)
|
|
* [Change icons](#change-icons)
|
|
* [Examples](#examples)
|
|
* [Example 1 : Hello World](#example-1-hello-world)
|
|
* [Example 2 : Web App](#example2-web-app)
|
|
|
|
## Usage
|
|
*[back to top](#top)*
|
|
|
|
### Node module
|
|
|
|
```javascript
|
|
const faDiagrams = require('fa-diagrams');
|
|
|
|
// data: example1
|
|
const data = {
|
|
"nodes": [
|
|
{
|
|
"name": "node1",
|
|
"icon": "laptop-code",
|
|
"color": "#4E342E",
|
|
"bottom": "my app"
|
|
},
|
|
{
|
|
"name": "node2",
|
|
"icon": "globe",
|
|
"color": "#455A64",
|
|
"bottom": "world"
|
|
}
|
|
],
|
|
"links": [
|
|
{
|
|
"from": "node1",
|
|
"to": "node2",
|
|
"color": "#333333",
|
|
"top": {
|
|
"icon": "envelope"
|
|
},
|
|
"bottom": "\"hello\""
|
|
}
|
|
]
|
|
}
|
|
|
|
const svg = faDiagrams.compute(data); // string containing xml data
|
|
|
|
//export as SVG with fs
|
|
const fs = require('fs');
|
|
fs.writeFileSync('diagram.svg', svg, {encoding:'utf-8'});
|
|
|
|
//export as PNG with svg2img (npm i svg2img)
|
|
const svg2img = require('svg2img');
|
|
svg2img(svg, function(error, buffer) {
|
|
fs.writeFileSync('diagram.png', buffer);
|
|
});
|
|
```
|
|
|
|
Will produce the diagram above
|
|
|
|
|
|
### Html script
|
|
|
|
```html
|
|
<head>
|
|
...
|
|
<script src="fa-diagrams-data.min.js"></script>
|
|
<script src="fa-diagrams.min.js"></script>
|
|
...
|
|
</head>
|
|
<body>
|
|
...
|
|
<script>
|
|
...
|
|
const svg = faDiagrams.compute(data); // string containing xml data
|
|
...
|
|
</script>
|
|
...
|
|
</body>
|
|
</html>
|
|
```
|
|
|
|
## Install
|
|
*[back to top](#top)*
|
|
|
|
### Static scripts
|
|
|
|
Get the scripts from this repository `dist` folder
|
|
|
|
```html
|
|
<script src="fa-diagrams-data.min.js"></script> <!-- 1.04 MB -->
|
|
<script src="fa-diagrams.min.js"></script> <!-- 110.40 KB -->
|
|
```
|
|
|
|
### CDN
|
|
|
|
```html
|
|
<script src="https://cdn.jsdelivr.net/npm/fa-diagrams@latest/dist/fa-diagrams-data.min.js"></script>
|
|
<script src="https://cdn.jsdelivr.net/npm/fa-diagrams@latest/dist/fa-diagrams.min.js"></script>
|
|
```
|
|
|
|
or
|
|
|
|
```html
|
|
<script src="https://unpkg.com/fa-diagrams/dist/fa-diagrams-data.min.js"></script>
|
|
<script src="https://unpkg.com/fa-diagrams/dist/fa-diagrams.min.js"></script>
|
|
```
|
|
|
|
### NPM
|
|
|
|
```
|
|
npm install fa-diagrams
|
|
```
|
|
|
|
### Build from sources
|
|
|
|
You will need subversion installed (used for precise folder fetching in GitHub)
|
|
|
|
```
|
|
git clone https://github.com/klemek/fa-diagrams.git
|
|
cd fa-diagrams
|
|
npm install
|
|
node build.sh
|
|
```
|
|
|
|
## API
|
|
*[back to top](#top)*
|
|
|
|
**You must pass as argument an object containing 3 keys:**
|
|
* [`options`](#options)
|
|
* [`nodes`](#nodes)
|
|
* [`links`](#links)
|
|
|
|
### `options`
|
|
|
|
| Key (`.subkey`) | Default value | Info | Redefined |
|
|
| --- | --- | --- | --- |
|
|
| `placing.max-link-length` | 3 | maximum stretching of links between nodes | no |
|
|
| `placing.diagonals` | `true` | allow diagonal links to be made | no |
|
|
| `rendering.beautify` | `false` | output a readable SVG file | no |
|
|
| `rendering.scale` | 256 | (in pixels) final icons size | no |
|
|
| `rendering.color` | `black` | color of all elements | no |
|
|
| `rendering.h-spacing` | 1.3 | how width is stretched comparing to height | no |
|
|
| `rendering.icons.scale` | 1 | default scaling of icons | in node |
|
|
| `rendering.icons.color` | `''` | color of all icons | in node |
|
|
| `rendering.sub-icons.scale` | 0.4 | default scaling of sub-icons | in sub-icon |
|
|
| `rendering.sub-icons.color` | `''` | color of all sub-icons | in sub-icon |
|
|
| `rendering.sub-icons.margin` | 0.3 | margin between sub-icons and elements | in sub-icon |
|
|
| `rendering.links.scale` | 1 | default scaling of links | in link |
|
|
| `rendering.links.color` | `''` | color of all links (might be redefined in link definition) | in link |
|
|
| `rendering.links.size` | 0 | forced size/length of the links (0 means it will be computed from the distance between the nodes) | in link |
|
|
| `rendering.texts.font` | `'Arial'` | font family of the texts (might be redefined in sub-elements definition) | in text |
|
|
| `rendering.texts.font-size` | 15 | font size of the texts | in sub-text |
|
|
| `rendering.texts.font-style` | `'normal'` | font style of the texts (see [Font styles](#font-styles)) | in sub-text |
|
|
| `rendering.texts.color` | `''` | color of all texts | in sub-text |
|
|
| `rendering.texts.margin` | 0.2 | margin between texts and elements | in sub-text |
|
|
| `rendering.texts.line-height` | 1.2 | height of each line in font size | in sub-text |
|
|
|
|
### `nodes`
|
|
|
|
Array of object as following:
|
|
|
|
| Key | Type | Required | Info |
|
|
| --- | --- | --- | --- |
|
|
| **`name`** | string | **yes** | used in links to reference nodes |
|
|
| **`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) |
|
|
| `color` | string | no | redefined the color |
|
|
| `scale` | number | no | redefine this node icon scale |
|
|
| `x`, `y` | number | no | force the position of this node |
|
|
|
|
### `links`
|
|
|
|
Array of object as following:
|
|
|
|
| Key | Type | Required | Info |
|
|
| --- | --- | --- | --- |
|
|
| **`from`** | string | **yes** | source node name |
|
|
| **`to`** | string | **yes** | destination node name |
|
|
| `type` | string | no | link's appearance (see [Link types](#link-types)) |
|
|
| `top`, `bottom` **or** `left`, `right` | string or object | no | left and right are relative of the link's direction, top and bottom relative of the link's angle, see [Sub-elements](#sub-elements) |
|
|
| `color` | string | no | redefine the color |
|
|
| `scale` | number | no | redefine this link scale |
|
|
| `size` | number | no | forced size/length of the link |
|
|
|
|
### Sub-elements
|
|
|
|
Elements meant to be drawn along-side a node/link.
|
|
There are two types: text and icons
|
|
|
|
### Texts
|
|
|
|
You can **just enter a string** to be considered a text but you can define a text with more options as following:
|
|
|
|
| Key | Type | Required | Info |
|
|
| --- | --- | --- | --- |
|
|
| **`text`** | string | **yes** | value of your text |
|
|
| `color` | string | no | redefine the color |
|
|
| `font` | string | no | redefine the font family |
|
|
| `font-size` | number | no | redefine the font size |
|
|
| `font-style` | string | no | redefine the font style (see [Font styles](#font-styles)) |
|
|
| `margin` | number | no | redefine the margin with the parent element |
|
|
| `line-height` | number | no | height of each line in font size |
|
|
|
|
### Icons
|
|
|
|
You can define a relative icon with the following:
|
|
|
|
| Key | Type | Required | Info |
|
|
| --- | --- | --- | --- |
|
|
| **`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 |
|
|
| `scale` | number | no | redefine this sub-icon scale |
|
|
| `margin` | number | no | redefine the margin with the parent element |
|
|
|
|
## More info
|
|
*[back to top](#top)*
|
|
|
|
### Icon names
|
|
|
|
**Icons are fetched from [Font-Awesome free icons](https://fontawesome.com/icons?d=gallery&m=free).**
|
|
When you reference an icon, for example `circle`, it's searched in the `solid` folder then `regular` then `brands`.
|
|
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.
|
|
|
|
|
|
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
|
|
|
|
Here are the accepted types and their preview :
|
|
|
|

|
|
|
|
You can use **`none`** to make an invisible link.
|
|
|
|
### Font styles
|
|
|
|
First, you should use [web-safe fonts](https://websitesetup.org/web-safe-fonts-html-css/) to be sure your SVG will be rendered correctly
|
|
|
|
Here are the available styles :
|
|
|
|
* `normal`
|
|
* **`bold`**
|
|
* *`italic`*
|
|
* `oblique`
|
|
* __`underlined`__
|
|
* `overlined`
|
|
* ~~`striked`~~
|
|
|
|
The style can also be a compound like `bold italic`.
|
|
|
|
### Thrown errors
|
|
|
|
Errors can be thrown in these 2 cases :
|
|
|
|
* Nodes could not be placed based on the constraints:
|
|
* `Failed to place nodes`
|
|
* A node or a link have an invalid property
|
|
* `Node 'name' is invalid at key ...`
|
|
|
|
### Change icons
|
|
|
|
If you want to change the icons you can edit/build your own `resources.json` as following:
|
|
|
|
```javascript
|
|
{
|
|
"name";: "squares",
|
|
"height";: 60, //height of all icons
|
|
"index";: [ // which categories are there and in which order it should be searched
|
|
"solid",
|
|
"hollow"
|
|
],
|
|
"icons";: {
|
|
"solid";: {
|
|
"square";:{
|
|
"path";:"M10 10v-40h40v40z",
|
|
"width";:60
|
|
}
|
|
},
|
|
"hollow";: {
|
|
"square";:{
|
|
"path";:"M10 10v-40h40v40h-40m10 10v-20h20v20h-20z",
|
|
"width";:60
|
|
}
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
## Examples
|
|
*[back to top](#top)*
|
|
|
|
### Example 1 : Hello World
|
|
|
|

|
|
|
|
<details>
|
|
<summary>JSON data (click)</summary>
|
|
<p>
|
|
|
|
<!-- data: example1 -->
|
|
```json
|
|
{
|
|
"nodes": [
|
|
{
|
|
"name": "node1",
|
|
"icon": "laptop-code",
|
|
"color": "#4E342E",
|
|
"bottom": "my app"
|
|
},
|
|
{
|
|
"name": "node2",
|
|
"icon": "globe",
|
|
"color": "#455A64",
|
|
"bottom": "world"
|
|
}
|
|
],
|
|
"links": [
|
|
{
|
|
"from": "node1",
|
|
"to": "node2",
|
|
"color": "#333333",
|
|
"top": {
|
|
"icon": "envelope"
|
|
},
|
|
"bottom": "\"hello\""
|
|
}
|
|
]
|
|
}
|
|
```
|
|
</p>
|
|
</details>
|
|
|
|
<details>
|
|
<summary>YAML data (click)</summary>
|
|
<p>
|
|
|
|
<!-- data: example1 -->
|
|
```yaml
|
|
nodes:
|
|
- name: node1
|
|
icon: laptop-code
|
|
color: '#4E342E'
|
|
bottom: my app
|
|
- name: node2
|
|
icon: globe
|
|
color: '#455A64'
|
|
bottom: world
|
|
links:
|
|
- from: node1
|
|
to: node2
|
|
color: '#333333'
|
|
top:
|
|
icon: envelope
|
|
bottom: '"hello"'
|
|
|
|
```
|
|
</p>
|
|
</details>
|
|
|
|
<details>
|
|
<summary>TOML data (click)</summary>
|
|
<p>
|
|
|
|
<!-- data: example1 -->
|
|
```toml
|
|
[[nodes]]
|
|
name = "node1"
|
|
icon = "laptop-code"
|
|
color = "#4E342E"
|
|
bottom = "my app"
|
|
|
|
[[nodes]]
|
|
name = "node2"
|
|
icon = "globe"
|
|
color = "#455A64"
|
|
bottom = "world"
|
|
|
|
[[links]]
|
|
from = "node1"
|
|
to = "node2"
|
|
color = "#333333"
|
|
bottom = '"hello"'
|
|
|
|
[links.top]
|
|
icon = "envelope"
|
|
|
|
```
|
|
</p>
|
|
</details>
|
|
|
|
### Example 2 : Web App
|
|
|
|

|
|
|
|
<details>
|
|
<summary>JSON data (click)</summary>
|
|
<p>
|
|
|
|
<!-- data: example2 -->
|
|
```json
|
|
{
|
|
"options": {
|
|
"placing": {
|
|
"diagonals": false
|
|
},
|
|
"rendering": {
|
|
"icons": {
|
|
"color": "#00695C"
|
|
},
|
|
"links": {
|
|
"color": "#26A69A"
|
|
},
|
|
"texts": {
|
|
"color": "#004D40",
|
|
"font": "mono",
|
|
"font-size": 12,
|
|
"margin": 0.25
|
|
},
|
|
"sub-icons": {
|
|
"color": "#004D40"
|
|
}
|
|
}
|
|
},
|
|
"nodes": [
|
|
{
|
|
"name": "client",
|
|
"icon": "laptop",
|
|
"bottom": "user"
|
|
},
|
|
{
|
|
"name": "page",
|
|
"icon": "file-code",
|
|
"top": "index.html"
|
|
},
|
|
{
|
|
"name": "js",
|
|
"icon": "js-square",
|
|
"bottom": "front-end"
|
|
},
|
|
{
|
|
"name": "server",
|
|
"icon": "node",
|
|
"bottom": "back-end"
|
|
},
|
|
{
|
|
"name": "db",
|
|
"icon": "database"
|
|
}
|
|
],
|
|
"links": [
|
|
{
|
|
"from": "client",
|
|
"to": "page"
|
|
},
|
|
{
|
|
"from": "page",
|
|
"to": "js",
|
|
"type": "double",
|
|
"top": {
|
|
"icon": "vuejs"
|
|
},
|
|
"bottom": "VueJS",
|
|
"direction": "down"
|
|
},
|
|
{
|
|
"from": "js",
|
|
"to": "server",
|
|
"type": "split-double",
|
|
"direction": "right",
|
|
"top": {
|
|
"text": "Ajax"
|
|
},
|
|
"bottom": {
|
|
"text": "JSON"
|
|
}
|
|
},
|
|
{
|
|
"from": "db",
|
|
"to": "server",
|
|
"type": "double",
|
|
"bottom": "Sequelize"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
</p>
|
|
</details>
|
|
|
|
<details>
|
|
<summary>YAML data (click)</summary>
|
|
<p>
|
|
|
|
<!-- data: example2 -->
|
|
```yaml
|
|
options:
|
|
placing:
|
|
diagonals: false
|
|
rendering:
|
|
icons:
|
|
color: '#00695C'
|
|
links:
|
|
color: '#26A69A'
|
|
texts:
|
|
color: '#004D40'
|
|
font: mono
|
|
font-size: 12
|
|
margin: 0.25
|
|
sub-icons:
|
|
color: '#004D40'
|
|
nodes:
|
|
- name: client
|
|
icon: laptop
|
|
bottom: user
|
|
- name: page
|
|
icon: file-code
|
|
top: index.html
|
|
- name: js
|
|
icon: js-square
|
|
bottom: front-end
|
|
- name: server
|
|
icon: node
|
|
bottom: back-end
|
|
- name: db
|
|
icon: database
|
|
links:
|
|
- from: client
|
|
to: page
|
|
- from: page
|
|
to: js
|
|
type: double
|
|
top:
|
|
icon: vuejs
|
|
bottom: VueJS
|
|
direction: down
|
|
- from: js
|
|
to: server
|
|
type: split-double
|
|
direction: right
|
|
top:
|
|
text: Ajax
|
|
bottom:
|
|
text: JSON
|
|
- from: db
|
|
to: server
|
|
type: double
|
|
bottom: Sequelize
|
|
|
|
```
|
|
</p>
|
|
</details>
|
|
|
|
<details>
|
|
<summary>TOML data (click)</summary>
|
|
<p>
|
|
|
|
<!-- data: example2 -->
|
|
```toml
|
|
[options.placing]
|
|
diagonals = false
|
|
|
|
[options.rendering.icons]
|
|
color = "#00695C"
|
|
|
|
[options.rendering.links]
|
|
color = "#26A69A"
|
|
|
|
[options.rendering.texts]
|
|
color = "#004D40"
|
|
font = "mono"
|
|
font-size = 12
|
|
margin = 0.25
|
|
|
|
[options.rendering.sub-icons]
|
|
color = "#004D40"
|
|
|
|
[[nodes]]
|
|
name = "client"
|
|
icon = "laptop"
|
|
bottom = "user"
|
|
|
|
[[nodes]]
|
|
name = "page"
|
|
icon = "file-code"
|
|
top = "index.html"
|
|
|
|
[[nodes]]
|
|
name = "js"
|
|
icon = "js-square"
|
|
bottom = "front-end"
|
|
|
|
[[nodes]]
|
|
name = "server"
|
|
icon = "node"
|
|
bottom = "back-end"
|
|
|
|
[[nodes]]
|
|
name = "db"
|
|
icon = "database"
|
|
|
|
[[links]]
|
|
from = "client"
|
|
to = "page"
|
|
|
|
[[links]]
|
|
from = "page"
|
|
to = "js"
|
|
type = "double"
|
|
bottom = "VueJS"
|
|
direction = "down"
|
|
|
|
[links.top]
|
|
icon = "vuejs"
|
|
|
|
[[links]]
|
|
from = "js"
|
|
to = "server"
|
|
type = "split-double"
|
|
direction = "right"
|
|
|
|
[links.top]
|
|
text = "Ajax"
|
|
|
|
[links.bottom]
|
|
text = "JSON"
|
|
|
|
[[links]]
|
|
from = "db"
|
|
to = "server"
|
|
type = "double"
|
|
bottom = "Sequelize"
|
|
|
|
```
|
|
</p>
|
|
</details>
|