PlantUML integration
This commit is contained in:
@@ -0,0 +1,2 @@
|
|||||||
|
/node_modules
|
||||||
|
/src/lib
|
||||||
@@ -6,13 +6,8 @@ cache:
|
|||||||
npm: true
|
npm: true
|
||||||
directories:
|
directories:
|
||||||
- node_modules
|
- node_modules
|
||||||
addons:
|
|
||||||
apt:
|
|
||||||
packages:
|
|
||||||
- graphviz
|
|
||||||
install:
|
install:
|
||||||
- npm install
|
- npm install
|
||||||
- npm install node-plantuml
|
|
||||||
before_script:
|
before_script:
|
||||||
- npm install -g jshint
|
- npm install -g jshint
|
||||||
script:
|
script:
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ On the `/rss` endpoint, the servers gives you a RSS feed based on the list of ar
|
|||||||
#### 1. Download and install the latest version from the repo
|
#### 1. Download and install the latest version from the repo
|
||||||
```bash
|
```bash
|
||||||
git clone https://github.com/klemek/gitblog.md.git
|
git clone https://github.com/klemek/gitblog.md.git
|
||||||
npm install
|
npm install --production
|
||||||
```
|
```
|
||||||
#### 2. Create your config file
|
#### 2. Create your config file
|
||||||
```bash
|
```bash
|
||||||
@@ -198,7 +198,9 @@ Any URL like `/year/month/day/anything/` will redirect to this article (and link
|
|||||||
* **Prism**
|
* **Prism**
|
||||||
It highlight code blocks to be more readable (more info [here](https://prismjs.com/), you will need the corresponding CSS file on your templates)
|
It highlight code blocks to be more readable (more info [here](https://prismjs.com/), you will need the corresponding CSS file on your templates)
|
||||||
* **MathJax**
|
* **MathJax**
|
||||||
It allows you to add math equations to your articles by simply writing LaTeX between $$ for full size (and between $ for inline) (more info [here](https://www.mathjax.org/))
|
It allows you to add math equations to your articles by simply writing LaTeX between `$$` for full size (and between $ for inline) (more info [here](https://www.mathjax.org/))
|
||||||
|
* **PlantUML**
|
||||||
|
It allows you to add UML diagrams with PlantUML Syntax between `@startuml` and `@enduml` (more info [here](http://www.plantuml.com))
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
[back to top](#gitblog-md)
|
[back to top](#gitblog-md)
|
||||||
@@ -222,6 +224,8 @@ Any URL like `/year/month/day/anything/` will redirect to this article (and link
|
|||||||
activate Prism code highlighting
|
activate Prism code highlighting
|
||||||
* `mathjax` (default: true)
|
* `mathjax` (default: true)
|
||||||
activate MathJax equations formatting
|
activate MathJax equations formatting
|
||||||
|
* `plantuml` (default: true)
|
||||||
|
activate PlantUML diagram rendering
|
||||||
* `home`
|
* `home`
|
||||||
* `index` (default: index.ejs)
|
* `index` (default: index.ejs)
|
||||||
the name of the home page template on the data directory
|
the name of the home page template on the data directory
|
||||||
|
|||||||
Generated
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "gitblog.md",
|
"name": "gitblog.md",
|
||||||
"version": "1.0.2",
|
"version": "1.0.3",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
+2
-1
@@ -43,7 +43,8 @@
|
|||||||
"src/**/*.js",
|
"src/**/*.js",
|
||||||
"!/node_modules/",
|
"!/node_modules/",
|
||||||
"!src/server.js",
|
"!src/server.js",
|
||||||
"!src/postinstall.js"
|
"!src/postinstall.js",
|
||||||
|
"!src/lib/*.js"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ If you see this page, that means it's working
|
|||||||
* [Check Boxes](#checkboxes)
|
* [Check Boxes](#checkboxes)
|
||||||
* [Spoilers](#spoilers)
|
* [Spoilers](#spoilers)
|
||||||
* [Math Equations](#mathequations)
|
* [Math Equations](#mathequations)
|
||||||
|
* [UML](#uml)
|
||||||
* [Youtube Videos](#youtubevideos)
|
* [Youtube Videos](#youtubevideos)
|
||||||
|
|
||||||
### Headers
|
### Headers
|
||||||
@@ -224,6 +225,33 @@ $$
|
|||||||
|
|
||||||
Where $\alpha$ is cool
|
Where $\alpha$ is cool
|
||||||
|
|
||||||
|
### UML
|
||||||
|
[Back to top](#top)
|
||||||
|
|
||||||
|
You can use PlantUML diagrams with `@startuml` and `@enduml` tags :
|
||||||
|
|
||||||
|
@startuml
|
||||||
|
title Article
|
||||||
|
cloud web
|
||||||
|
node nodejs {
|
||||||
|
TCP -right- [express]
|
||||||
|
[showdown]
|
||||||
|
}
|
||||||
|
package data {
|
||||||
|
package "2019/06/18" {
|
||||||
|
component index [
|
||||||
|
index.md
|
||||||
|
image.png
|
||||||
|
...
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
web -down-> TCP : 1. /2019/06/18/title
|
||||||
|
express -down-> index : 2. fetch
|
||||||
|
index -up-> showdown : 3. markdown
|
||||||
|
showdown -left-> express : 4. html
|
||||||
|
express -up-> web : 5. html
|
||||||
|
@enduml
|
||||||
|
|
||||||
### Youtube Videos
|
### Youtube Videos
|
||||||
[Back to top](#top)
|
[Back to top](#top)
|
||||||
|
|||||||
@@ -8,7 +8,8 @@
|
|||||||
"rss": true,
|
"rss": true,
|
||||||
"webhook": true,
|
"webhook": true,
|
||||||
"prism": true,
|
"prism": true,
|
||||||
"mathjax": true
|
"mathjax": true,
|
||||||
|
"plantuml": true
|
||||||
},
|
},
|
||||||
"home": {
|
"home": {
|
||||||
"index": "index.ejs",
|
"index": "index.ejs",
|
||||||
@@ -47,5 +48,8 @@
|
|||||||
"mathjax": {
|
"mathjax": {
|
||||||
"output_format": "svg",
|
"output_format": "svg",
|
||||||
"speak_text": true
|
"speak_text": true
|
||||||
|
},
|
||||||
|
"plantuml": {
|
||||||
|
"output_format": "svg"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
+27
-4
@@ -1,4 +1,5 @@
|
|||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
const showdown = require('showdown');
|
const showdown = require('showdown');
|
||||||
|
|
||||||
module.exports = (config) => {
|
module.exports = (config) => {
|
||||||
@@ -31,6 +32,25 @@ module.exports = (config) => {
|
|||||||
cb(data);
|
cb(data);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (config['modules']['plantuml']) {
|
||||||
|
require('./script_loader')(path.join(__dirname, 'lib', 'plantuml_synchro.js'));
|
||||||
|
}
|
||||||
|
|
||||||
|
const renderPlantUML = (data, cb) => {
|
||||||
|
if (!config['modules']['plantuml'])
|
||||||
|
return cb(data);
|
||||||
|
const umlRegex = /@startuml\r?\n((?:(?!@enduml)[\s\S])*)\r?\n@enduml/m;
|
||||||
|
let match;
|
||||||
|
while ((match = umlRegex.exec(data))) {
|
||||||
|
const code = match[1].trim();
|
||||||
|
const s = unescape(encodeURIComponent(code)); // jshint ignore:line
|
||||||
|
const compressed = global['zip_deflate'](s);
|
||||||
|
const url = `http://www.plantuml.com/plantuml/${config['plantuml']['output_format']}/${encode64(compressed)}`;// jshint ignore:line
|
||||||
|
data = data.slice(0, match.index) + `<img alt="generated PlantUML diagram" src="${url}">` + data.slice(match.index + match[0].length);
|
||||||
|
}
|
||||||
|
cb(data);
|
||||||
|
};
|
||||||
|
|
||||||
let mjAPI;
|
let mjAPI;
|
||||||
if (config['modules']['mathjax']) {
|
if (config['modules']['mathjax']) {
|
||||||
mjAPI = require('mathjax-node');
|
mjAPI = require('mathjax-node');
|
||||||
@@ -81,16 +101,19 @@ module.exports = (config) => {
|
|||||||
return {
|
return {
|
||||||
renderShowDown: config['test'] ? renderShowDown : undefined,
|
renderShowDown: config['test'] ? renderShowDown : undefined,
|
||||||
renderPrism: config['test'] ? renderPrism : undefined,
|
renderPrism: config['test'] ? renderPrism : undefined,
|
||||||
|
renderPlantUML: config['test'] ? renderPlantUML : undefined,
|
||||||
renderMathJax: config['test'] ? renderMathJax : undefined,
|
renderMathJax: config['test'] ? renderMathJax : undefined,
|
||||||
render: (file, cb) => {
|
render: (file, cb) => {
|
||||||
fs.readFile(file, {encoding: 'UTF-8'}, (err, data) => {
|
fs.readFile(file, {encoding: 'UTF-8'}, (err, data) => {
|
||||||
if (err)
|
if (err)
|
||||||
return cb(err);
|
return cb(err);
|
||||||
|
|
||||||
renderPrism(data, (data2) => {
|
renderPrism(data, (data) => {
|
||||||
renderMathJax(data2, (data3) => {
|
renderPlantUML(data, (data) => {
|
||||||
renderShowDown(data3, (html) => {
|
renderMathJax(data, (data) => {
|
||||||
cb(null, html);
|
renderShowDown(data, (html) => {
|
||||||
|
cb(null, html);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
const fs = require('fs');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Import client-side script into the "global" var
|
||||||
|
* @param scriptPath
|
||||||
|
*/
|
||||||
|
module.exports = (scriptPath) => {
|
||||||
|
eval.call(global, fs.readFileSync(scriptPath, {encoding: 'UTF-8'}));
|
||||||
|
};
|
||||||
|
|
||||||
+31
-1
@@ -10,7 +10,8 @@ const config = {
|
|||||||
'test': true,
|
'test': true,
|
||||||
'modules': {
|
'modules': {
|
||||||
'prism': true,
|
'prism': true,
|
||||||
'mathjax': true
|
'mathjax': true,
|
||||||
|
'plantuml': true
|
||||||
},
|
},
|
||||||
'showdown': {
|
'showdown': {
|
||||||
'simplifiedAutoLink': true,
|
'simplifiedAutoLink': true,
|
||||||
@@ -19,6 +20,9 @@ const config = {
|
|||||||
'mathjax': {
|
'mathjax': {
|
||||||
'output_format': 'html',
|
'output_format': 'html',
|
||||||
'speak_text': false
|
'speak_text': false
|
||||||
|
},
|
||||||
|
'plantuml': {
|
||||||
|
'output_format': 'svg'
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -27,6 +31,7 @@ const renderer = require('../src/renderer')(config);
|
|||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
config['modules']['prism'] = true;
|
config['modules']['prism'] = true;
|
||||||
config['modules']['mathjax'] = true;
|
config['modules']['mathjax'] = true;
|
||||||
|
config['modules']['plantuml'] = true;
|
||||||
utils.deleteFolderSync(dataDir);
|
utils.deleteFolderSync(dataDir);
|
||||||
fs.mkdirSync(dataDir);
|
fs.mkdirSync(dataDir);
|
||||||
});
|
});
|
||||||
@@ -91,6 +96,31 @@ describe('Test Prism', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('Test PlantUML', () => {
|
||||||
|
test('no plantuml', (done) => {
|
||||||
|
config['modules']['plantuml'] = false;
|
||||||
|
renderer.renderPlantUML('@startuml\nBob -> Alice : hello\n@enduml', (data) => {
|
||||||
|
expect(data).toBe('@startuml\nBob -> Alice : hello\n@enduml');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('plantuml correct', (done) => {
|
||||||
|
renderer.renderPlantUML('@startuml\nBob -> Alice : hello\n@enduml', (data) => {
|
||||||
|
expect(data).toBe('<img alt="generated PlantUML diagram" src="http://www.plantuml.com/plantuml/svg/SyfFKj2rKt3CoKnELR1Io4ZDoSa70000">');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('plantuml multiple uml', (done) => {
|
||||||
|
renderer.renderPlantUML('@startuml\nBob -> Alice : hello\n@enduml\n@startuml\nBob -> Alice : hello\n@enduml', (data) => {
|
||||||
|
expect(data).toBe('<img alt="generated PlantUML diagram" src="http://www.plantuml.com/plantuml/svg/SyfFKj2rKt3CoKnELR1Io4ZDoSa70000">\n<img alt="generated PlantUML diagram" src="http://www.plantuml.com/plantuml/svg/SyfFKj2rKt3CoKnELR1Io4ZDoSa70000">');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
describe('Test MathJax', () => {
|
describe('Test MathJax', () => {
|
||||||
test('no mathjax', (done) => {
|
test('no mathjax', (done) => {
|
||||||
config['modules']['mathjax'] = false;
|
config['modules']['mathjax'] = false;
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
/* jshint -W117 */
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
const utils = require('./test_utils');
|
||||||
|
|
||||||
|
const dataDir = 'test_data';
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
utils.deleteFolderSync(dataDir);
|
||||||
|
fs.mkdirSync(dataDir);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterAll(() => {
|
||||||
|
if (fs.existsSync(dataDir)) {
|
||||||
|
utils.deleteFolderSync(dataDir);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
test('load 1 script', () => {
|
||||||
|
const file = path.join(dataDir, 'test.js');
|
||||||
|
fs.writeFileSync(file, `
|
||||||
|
var a = 5;
|
||||||
|
function b(){
|
||||||
|
return a;
|
||||||
|
}`);
|
||||||
|
require('../src/script_loader')(file);
|
||||||
|
expect(global['b']).toBeDefined();
|
||||||
|
expect(global['b']()).toBe(5);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('load 2 script', () => {
|
||||||
|
const file1 = path.join(dataDir, 'test.js');
|
||||||
|
fs.writeFileSync(file1, `
|
||||||
|
var a = 5;
|
||||||
|
function b(){
|
||||||
|
return a;
|
||||||
|
}`);
|
||||||
|
const file2 = path.join(dataDir, 'test2.js');
|
||||||
|
fs.writeFileSync(file2, `
|
||||||
|
var a = 9;
|
||||||
|
function b(){
|
||||||
|
return a;
|
||||||
|
}`);
|
||||||
|
require('../src/script_loader')(file1);
|
||||||
|
expect(global['b']).toBeDefined();
|
||||||
|
expect(global['b']()).toBe(5);
|
||||||
|
|
||||||
|
require('../src/script_loader.js')(file2);
|
||||||
|
expect(global['b']).toBeDefined();
|
||||||
|
expect(global['b']()).toBe(9);
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user