Compare commits

..

53 Commits

Author SHA1 Message Date
Klemek 32f9ea74f1 Merge pull request #27 from Klemek/dev
GitBlog v1.2.8
2019-09-19 20:38:38 +02:00
Klemek 9d1fb69fee nvm 2019-09-19 20:37:40 +02:00
Klemek 24a02d862f fml2 2019-09-19 20:30:35 +02:00
Klemek cfe9965d03 fml 2019-09-19 20:28:20 +02:00
Klemek d260b9d2f8 Merge pull request #26 from Klemek/dev
GitBlog v1.2.8
2019-09-19 20:13:36 +02:00
Klemek 9ec55b3c01 dependencies fix ffs 2019-09-19 20:12:49 +02:00
Klemek c693d96339 Merge pull request #25 from Klemek/dev
GitBlog v1.2.8
2019-09-19 20:09:57 +02:00
Klemek 8bb6b6db66 Merge branch 'master' into dev 2019-09-19 20:07:59 +02:00
Klemek 849cdf2a19 dependencies fix FINALLY 2019-09-19 20:05:10 +02:00
Klemek d0d3f94049 wtf2 2019-09-19 20:02:23 +02:00
Klemek 613e663c13 wtf 2019-09-19 20:01:32 +02:00
Klemek bd10871da9 Merge branch 'dev' 2019-09-19 19:52:55 +02:00
Klemek 671a4314d7 Merge branch 'master' into dev 2019-09-19 19:51:04 +02:00
Klemek 1cee7094f3 Delete package-lock.json 2019-09-19 19:47:33 +02:00
Klemek 2284d46bb5 Merge remote-tracking branch 'origin/dev' into dev 2019-09-19 19:46:19 +02:00
Klemek 7245876b07 dependencies fix 2019-09-19 19:46:09 +02:00
Klemek 7a35aec7ad Merge pull request #23 from Klemek/dependabot/npm_and_yarn/mixin-deep-1.3.2
Bump mixin-deep from 1.3.1 to 1.3.2
2019-09-19 19:27:34 +02:00
dependabot[bot] 870701b6c6 Bump mixin-deep from 1.3.1 to 1.3.2
Bumps [mixin-deep](https://github.com/jonschlinkert/mixin-deep) from 1.3.1 to 1.3.2.
- [Release notes](https://github.com/jonschlinkert/mixin-deep/releases)
- [Commits](https://github.com/jonschlinkert/mixin-deep/compare/1.3.1...1.3.2)

Signed-off-by: dependabot[bot] <support@github.com>
2019-09-19 17:23:38 +00:00
Klemek 3be86dec58 Merge pull request #22 from Klemek/dev
GitBlog.md v1.2.8
2019-09-19 19:22:16 +02:00
Klemek 48d9535007 Merge branch 'master' into dev 2019-09-19 19:16:59 +02:00
Klemek ae2eb52cf8 [skip CI]updated README.md 2019-09-19 19:16:31 +02:00
Klemek 7e9e1e19fa changed version number 2019-09-19 19:14:16 +02:00
Klemek c9ef93088b express rate limit 2019-09-19 19:13:41 +02:00
Klemek 99e4bb5c4d [skip CI] lgtm config 2019-09-19 19:03:49 +02:00
Klemek dd5af2b865 [skip CI] update README.md 2019-09-19 09:26:17 +02:00
Klemek 4671253147 Merge pull request #21 from Klemek/dev
v1.2.7
2019-08-19 14:34:32 +02:00
Klemek add01b28fe Update package.json 2019-08-19 14:25:01 +02:00
Klemek a27a53e238 faDiagram switch to TOML lang 2019-08-19 14:14:52 +02:00
Klemek 6aff9b4d93 Merge remote-tracking branch 'origin/dev' into dev 2019-08-19 14:14:05 +02:00
Klemek c9f57233a4 faDiagram switch to TOML lang 2019-08-19 14:13:54 +02:00
Klemek 7d72e94aa3 Merge pull request #20 from Klemek/dev
updated package-lock
2019-07-19 11:00:33 +02:00
Klemek 3d6a0b4306 Merge branch 'master' into dev 2019-07-19 10:58:52 +02:00
Klemek babc533efc updated package-lock 2019-07-19 10:56:26 +02:00
Klemek 36908134e6 Merge pull request #19 from Klemek/dependabot/npm_and_yarn/lodash-4.17.15
Bump lodash from 4.17.11 to 4.17.15
2019-07-19 10:50:53 +02:00
dependabot[bot] d426b41368 Bump lodash from 4.17.11 to 4.17.15
Bumps [lodash](https://github.com/lodash/lodash) from 4.17.11 to 4.17.15.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.11...4.17.15)

Signed-off-by: dependabot[bot] <support@github.com>
2019-07-19 08:48:39 +00:00
Klemek 1836a414eb Merge pull request #18 from Klemek/dev
v1.2.6
2019-07-19 10:46:33 +02:00
Klemek ca49a29dd9 [skip CI] updated version 2019-07-19 10:44:58 +02:00
Klemek 02a768a6af [skip CI] updated README.md 2019-07-19 10:44:26 +02:00
Klemek bbc4d7c270 [skip CI] updated README.md 2019-07-19 10:42:25 +02:00
Klemek bfa1521f85 updated sample to show fa-diagrams 2019-07-19 10:41:21 +02:00
Klemek a05d380fcf fixed parts detection 2019-07-19 10:41:01 +02:00
Klemek 4a32995ca1 fa-diagrams support 2019-07-19 10:19:12 +02:00
Klemek 53e1fe7201 mathjax/plantuml rendering only outside of code/scripts 2019-07-19 10:01:01 +02:00
Klemek 2e8ff1be92 fixed mathjax in code 2019-07-18 16:41:25 +02:00
Klemek e14f9fc4af Merge remote-tracking branch 'origin/dev' into dev 2019-07-18 14:07:34 +02:00
Klemek 896f302bcf updated default template 2019-07-18 14:07:24 +02:00
Klemek cc0bd1cf49 Merge pull request #17 from Klemek/dev
updated CI
2019-07-12 14:07:36 +02:00
Klemek 7a1d9cbbd6 Merge branch 'master' into dev 2019-07-12 13:59:54 +02:00
Clément GOUIN 34e8d4cb6f updated CI 2019-07-12 13:57:27 +02:00
Klemek 4a9b70ac68 Update .travis.yml 2019-07-12 13:53:55 +02:00
Klemek 889258c874 Update .travis.yml 2019-07-12 11:53:02 +02:00
Klemek 90c343c752 Merge remote-tracking branch 'origin/master' 2019-06-19 18:41:23 +02:00
Klemek ff7542af70 updated uml 2019-06-18 20:14:37 +02:00
15 changed files with 1545 additions and 5076 deletions
+2 -1
View File
@@ -11,5 +11,6 @@ install:
before_script: before_script:
- npm install -g jshint - npm install -g jshint
script: script:
- jest --silent --coverage --coverageReporters=text-lcov | coveralls - jest --coverage --silent
- jshint ./src - jshint ./src
- cat ./coverage/lcov.info | coveralls
+11 -3
View File
@@ -1,8 +1,9 @@
# GitBlog.md
[![Build Status](https://img.shields.io/travis/Klemek/GitBlog.md.svg?branch=master)](https://travis-ci.org/Klemek/GitBlog.md) [![Build Status](https://img.shields.io/travis/Klemek/GitBlog.md.svg?branch=master)](https://travis-ci.org/Klemek/GitBlog.md)
[![Coverage Status](https://img.shields.io/coveralls/github/Klemek/GitBlog.md.svg?branch=master)](https://coveralls.io/github/Klemek/GitBlog.md?branch=master) [![Coverage Status](https://img.shields.io/coveralls/github/Klemek/GitBlog.md.svg?branch=master)](https://coveralls.io/github/Klemek/GitBlog.md?branch=master)
[![Language grade: JavaScript](https://img.shields.io/lgtm/grade/javascript/g/Klemek/GitBlog.md.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/Klemek/GitBlog.md/context:javascript)
[![Total alerts](https://img.shields.io/lgtm/alerts/g/Klemek/GitBlog.md.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/Klemek/GitBlog.md/alerts/)
# GitBlog.md
A static blog using Markdown pulled from your git repository. A static blog using Markdown pulled from your git repository.
@@ -245,6 +246,9 @@ Any URL like `/year/month/day/anything/` will redirect to this article (and link
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** * **PlantUML**
It allows you to add UML diagrams with PlantUML Syntax between `@startuml` and `@enduml` (more info [here](http://www.plantuml.com)) It allows you to add UML diagrams with PlantUML Syntax between `@startuml` and `@enduml` (more info [here](http://www.plantuml.com))
* **fa-diagrams**
It allows you to define SVG diagrams with Font-Awesome icons in [TOML](https://github.com/toml-lang/toml) between `@startfad` and `@endfad` (more info [here](https://github.com/Klemek/fa-diagrams))
## Configuration ## Configuration
[back to top](#gitblog-md) [back to top](#gitblog-md)
@@ -258,6 +262,8 @@ Any URL like `/year/month/day/anything/` will redirect to this article (and link
the directory where will be located the git repo with templates and articles the directory where will be located the git repo with templates and articles
* `view_engine` (default: ejs) * `view_engine` (default: ejs)
the Express view engine used to render pages from templates the Express view engine used to render pages from templates
* `rate_limit` (default: 100)
number of requests allowed in a time-frame of 15 minutes
* `access_log` (default: access.log) * `access_log` (default: access.log)
log file where to save access requests (empty to disable) log file where to save access requests (empty to disable)
* `error_log` (default: error.log) * `error_log` (default: error.log)
@@ -273,6 +279,8 @@ Any URL like `/year/month/day/anything/` will redirect to this article (and link
activate MathJax equations formatting activate MathJax equations formatting
* `plantuml` (default: true) * `plantuml` (default: true)
activate PlantUML diagram rendering activate PlantUML diagram rendering
* `fa-diagrams` (default: true)
activate fa-diagrams rendering
* `home` * `home`
* `title` (default: GitBlog.md) * `title` (default: GitBlog.md)
the title of your blog, **strongly advised to be changed** the title of your blog, **strongly advised to be changed**
+7
View File
@@ -0,0 +1,7 @@
path_classifiers:
test:
- test
docs:
- uml
library:
- src/lib
+1241 -5039
View File
File diff suppressed because it is too large Load Diff
+4 -4
View File
@@ -1,13 +1,15 @@
{ {
"name": "gitblog.md", "name": "gitblog.md",
"version": "1.2.5", "version": "1.2.8",
"description": "A static blog using Markdown pulled from your git repository.", "description": "A static blog using Markdown pulled from your git repository.",
"main": "src/server.js", "main": "src/server.js",
"dependencies": { "dependencies": {
"@iarna/toml": "^2.2.3",
"body-parser": "^1.19.0", "body-parser": "^1.19.0",
"crypto": "^1.0.1",
"ejs": "^2.6.2", "ejs": "^2.6.2",
"express": "^4.17.1", "express": "^4.17.1",
"express-rate-limit": "^5.0.0",
"fa-diagrams": "^1.0.3",
"mathjax-node": "^2.1.1", "mathjax-node": "^2.1.1",
"ncp": "^2.0.0", "ncp": "^2.0.0",
"node-prismjs": "^0.1.2", "node-prismjs": "^0.1.2",
@@ -16,8 +18,6 @@
"showdown": "^1.9.0" "showdown": "^1.9.0"
}, },
"devDependencies": { "devDependencies": {
"babel-cli": "^6.26.0",
"babel-preset-env": "^1.7.0",
"coveralls": "^3.0.4", "coveralls": "^3.0.4",
"jest": "^24.8.0", "jest": "^24.8.0",
"superagent": "^5.1.0", "superagent": "^5.1.0",
+29
View File
@@ -19,6 +19,7 @@ If you see this page, that means it's working
* [Spoilers](#spoilers) * [Spoilers](#spoilers)
* [Math Equations](#mathequations) * [Math Equations](#mathequations)
* [UML](#uml) * [UML](#uml)
* [Diagrams](#diagrams)
* [Youtube Videos](#youtubevideos) * [Youtube Videos](#youtubevideos)
### Headers ### Headers
@@ -253,6 +254,34 @@ showdown -left-> express : 4. html
express -up-> web : 5. html express -up-> web : 5. html
@enduml @enduml
### Diagrams
[Back to top](#top)
You can use [fa-diagrams](https://github.com/Klemek/fa-diagrams) with `@startfad` and `@endfad` tags and using [TOML](https://github.com/toml-lang/toml) inside
@startfad
[[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"
@endfad
### Youtube Videos ### Youtube Videos
[Back to top](#top) [Back to top](#top)
+5 -3
View File
@@ -6,16 +6,18 @@
</head> </head>
<body> <body>
<main> <main>
<h1><%= info.title %></h1> <h1 class="title"><%= info.title %></h1>
<%= info.description %> <%= info.description %>
<h2>Articles in this blog :</h2> <h2>Articles in this blog :</h2>
<% articles.forEach((article) => { %> <% articles.forEach((article) => { %>
<div class="article"> <div class="article">
<h3><%- `<a href="${article.url}">${article.title}</a>` %></h3> <%- `<a href="${article.url}">` %>
<span class="time"><span>Published on</span> <%= article.year + '-' + article.month + '-' + article.day %></span> <h3><%- `${article.title}` %></h3>
<span class="time"><span>Published on</span>&nbsp;&nbsp;<%= article.year + '-' + ('0' + article.month).slice(-2) + '-' + ('0' + article.day).slice(-2) %></span>
<% if(article.thumbnail){ %> <% if(article.thumbnail){ %>
<%- `<img alt="thumbnail" src=${article.thumbnail}>` %> <%- `<img alt="thumbnail" src=${article.thumbnail}>` %>
<% } %> <% } %>
<%- `</a>` %>
</div> </div>
<% }); %> <% }); %>
<%- include('footer'); %> <%- include('footer'); %>
+26 -3
View File
@@ -16,7 +16,7 @@ body {
} }
main { main {
max-width: 42rem; max-width: 45rem;
padding: 2rem; padding: 2rem;
margin: auto; margin: auto;
background-color: #F0F0F0; background-color: #F0F0F0;
@@ -54,6 +54,13 @@ pre {
padding: 10px 16px; padding: 10px 16px;
} }
:not(pre) > code {
padding: 0.25em 0.5em;
border-radius: 0.25em;
background: #DDD;
font-size: 90%;
}
blockquote { blockquote {
border-left: 0.5em solid #ccc; border-left: 0.5em solid #ccc;
padding-left: 1em; padding-left: 1em;
@@ -108,10 +115,11 @@ main.article div.header a.link-home {
line-height: 2.4; line-height: 2.4;
} }
main.article div.header h1, main.article div.header h2 { main.article div.header h1, main.article div.header h2, .title {
margin-top: 0.85em; margin-top: 0.85em;
margin-bottom: 0.25em; margin-bottom: 0.25em;
font-size: 2em; font-size: 2em;
font-weight: bold;
} }
main.article div.header h1 a, main.article div.header h2 a, div.article h3 a { main.article div.header h1 a, main.article div.header h2 a, div.article h3 a {
@@ -129,6 +137,12 @@ div.article {
div.article h3 { div.article h3 {
font-size: 1.3em; font-size: 1.3em;
margin:0; margin:0;
color: #3C3CA1;
}
div.article a {
text-decoration: none;
color: inherit;
} }
div.article img{ div.article img{
@@ -138,6 +152,15 @@ div.article img{
margin-top:0.25em; margin-top:0.25em;
} }
div.article:hover {
opacity: 0.9;
}
div.article:active {
opacity: 0.8;
}
#text { #text {
text-align: justify; text-align: justify;
hyphens: auto; hyphens: auto;
@@ -147,7 +170,7 @@ div.article img{
text-align: left; text-align: left;
} }
#text img { #text img, #text svg {
max-width: 100%; max-width: 100%;
height: auto; height: auto;
} }
+1 -1
View File
@@ -9,7 +9,7 @@
<div class="header"> <div class="header">
<a class="link-home" href="/">↑</a> <a class="link-home" href="/">↑</a>
<h1><%= article.title %></h1> <h1><%= article.title %></h1>
<span class="time"><span>Published on</span> <%= article.year + '-' + article.month + '-' + article.day %></span> <span class="time"><span><%= article.draft ? 'Drafted on' : 'Published on' %></span>&nbsp;&nbsp;<%= article.year + '-' + ('0' + article.month).slice(-2) + '-' + ('0' + article.day).slice(-2) %></span>
</div> </div>
<div id="text"><%- article.content %></div> <div id="text"><%- article.content %></div>
<br> <br>
+8
View File
@@ -3,6 +3,7 @@ const app = express();
const fs = require('fs'); const fs = require('fs');
const path = require('path'); const path = require('path');
const pjson = require('../package.json'); const pjson = require('../package.json');
const rateLimit = require('express-rate-limit');
app.enable('trust proxy'); app.enable('trust proxy');
@@ -122,6 +123,13 @@ module.exports = (config) => {
next(); next();
}); });
//rate limit for safer server
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: config['rate_limit']
});
app.use(limiter);
//log request at result end //log request at result end
app.use((req, res, next) => { app.use((req, res, next) => {
if (config['access_log']) { if (config['access_log']) {
+3 -1
View File
@@ -3,6 +3,7 @@
"host": "", "host": "",
"data_dir": "data", "data_dir": "data",
"view_engine": "ejs", "view_engine": "ejs",
"rate_limit": 100,
"access_log": "access.log", "access_log": "access.log",
"error_log": "error.log", "error_log": "error.log",
"modules": { "modules": {
@@ -10,7 +11,8 @@
"webhook": true, "webhook": true,
"prism": true, "prism": true,
"mathjax": true, "mathjax": true,
"plantuml": true "plantuml": true,
"fa-diagrams": true
}, },
"home": { "home": {
"title": "GitBlog.md", "title": "GitBlog.md",
+118 -20
View File
@@ -5,6 +5,54 @@ const showdown = require('showdown');
module.exports = (config) => { module.exports = (config) => {
const converter = new showdown.Converter(config['showdown']); const converter = new showdown.Converter(config['showdown']);
/**
* get parts outside of codes/scripts
* @param {string} data
* @returns {{index:number, end:number, text:string}[]} parts
*/
const getParts = (data) => {
let parts = [];
let match;
let i = 0;
while ((match = /```/m.exec(data.slice(i)))) {
parts.push({
index: i,
text: data.slice(i, i + match.index),
});
i += match.index + match[0].length;
}
if (i < data.length)
parts.push({
index: i,
text: data.slice(i, data.length),
});
parts = parts.filter((p, i) => i % 2 === 0); //filter out code parts
// detect scripts outside of code
parts.forEach((p, pi) => {
let i = 0;
const subParts = [];
while ((match = /(<script>((?:(?!<\/script>)[\s\S])*)<\/script>)/gm.exec(p.text.slice(i)))) {
subParts.push({
index: p.index + i,
text: p.text.slice(i, i + match.index),
});
i += match.index + match[0].length;
}
if (i < p.text.length)
subParts.push({
index: p.index + i,
text: p.text.slice(i, p.text.length),
});
parts.splice(pi, 1, ...subParts);
});
parts.forEach(part => part.end = part.index + part.text.length);
return parts;
};
const renderShowDown = (data, cb) => { const renderShowDown = (data, cb) => {
const html = converter.makeHtml(data); const html = converter.makeHtml(data);
cb(html); cb(html);
@@ -35,15 +83,19 @@ module.exports = (config) => {
const renderPlantUML = (data, cb) => { const renderPlantUML = (data, cb) => {
if (!config['modules']['plantuml']) if (!config['modules']['plantuml'])
return cb(data); return cb(data);
const parts = getParts(data);
const umlRegex = /@startuml\r?\n((?:(?!@enduml)[\s\S])*)\r?\n@enduml/m; const umlRegex = /@startuml\r?\n((?:(?!@enduml)[\s\S])*)\r?\n@enduml/m;
let match; let match;
while ((match = umlRegex.exec(data))) { parts.forEach(part => {
const code = match[1].trim(); while ((match = umlRegex.exec(part.text))) {
const s = unescape(encodeURIComponent(code)); // jshint ignore:line const code = match[1].trim();
const compressed = global['zip_deflate'](s); const s = unescape(encodeURIComponent(code)); // jshint ignore:line
const url = `http://www.plantuml.com/plantuml/${config['plantuml']['output_format']}/${encode64(compressed)}`;// jshint ignore:line const compressed = global['zip_deflate'](s);
data = data.slice(0, match.index) + `<img alt="generated PlantUML diagram" src="${url}">` + data.slice(match.index + match[0].length); const url = `http://www.plantuml.com/plantuml/${config['plantuml']['output_format']}/${encode64(compressed)}`;// jshint ignore:line
} part.text = part.text.slice(0, match.index) + `<img alt="generated PlantUML diagram" src="${url}">` + part.text.slice(match.index + match[0].length);
}
data = data.slice(0, part.index) + part.text + data.slice(part.end);
});
cb(data); cb(data);
}; };
@@ -64,7 +116,9 @@ module.exports = (config) => {
if (!config['modules']['mathjax']) if (!config['modules']['mathjax'])
return cb(data); return cb(data);
const doMJ = (match, format) => { const parts = getParts(data);
const doMJ = (match, format, i) => {
const eq = match[1].trim(); const eq = match[1].trim();
const output = config['mathjax']['output_format']; const output = config['mathjax']['output_format'];
const mjConf = { const mjConf = {
@@ -74,7 +128,7 @@ module.exports = (config) => {
}; };
mjConf[output] = true; mjConf[output] = true;
mjAPI.typeset(mjConf, (res) => { mjAPI.typeset(mjConf, (res) => {
data = data.slice(0, match.index) + res[output] + data.slice(match.index + match[0].length); data = data.slice(0, parts[i].index + match.index) + res[output] + data.slice(parts[i].index + match.index + match[0].length);
renderMathJax(data, (data2) => { renderMathJax(data, (data2) => {
cb(data2); cb(data2);
}); });
@@ -84,31 +138,75 @@ module.exports = (config) => {
const eqRegex = /\$\$((?:(?!\$\$)[\s\S])*)\$\$/m; const eqRegex = /\$\$((?:(?!\$\$)[\s\S])*)\$\$/m;
const inlineEqRegex = /\$([^$\n]*)\$/; const inlineEqRegex = /\$([^$\n]*)\$/;
let match; for (let i = 0; i < parts.length; i++) {
if ((match = eqRegex.exec(data))) { let match;
doMJ(match, 'TeX'); if ((match = eqRegex.exec(parts[i].text))) {
} else if ((match = inlineEqRegex.exec(data))) { return doMJ(match, 'TeX', i);
doMJ(match, 'inline-TeX'); } else if ((match = inlineEqRegex.exec(parts[i].text))) {
} else { return doMJ(match, 'inline-TeX', i);
cb(data); }
} }
cb(data);
};
let faDiagrams;
let toml;
if (config['modules']['fa-diagrams']) {
faDiagrams = require('fa-diagrams');
toml = require('@iarna/toml');
}
const renderFaDiagrams = (data, cb) => {
if (!config['modules']['fa-diagrams'])
return cb(data);
const parts = getParts(data);
const diagramsRegex = /@startfad\r?\n((?:(?!@endfad)[\s\S])*)\r?\n@endfad/m;
let match;
parts.forEach(part => {
while ((match = diagramsRegex.exec(part.text))) {
const code = match[1].trim();
let output;
try {
const diagData = toml.parse(code);
const findLineBreaks = (data) => {
Object.keys(data).forEach(key => {
if (typeof data[key] === 'object')
findLineBreaks(data[key]);
else if (typeof data[key] === 'string')
data[key] = data[key].replace(/\\n/gm, '\n');
});
};
findLineBreaks(diagData);
output = faDiagrams.compute(diagData);
} catch (err) {
output = `<b style="color:red">${err.toString()}</b>`;
}
part.text = part.text.slice(0, match.index) + output + part.text.slice(match.index + match[0].length);
}
data = data.slice(0, part.index) + part.text + data.slice(part.end);
});
cb(data);
}; };
return { return {
getParts: config['test'] ? getParts : undefined,
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, renderPlantUML: config['test'] ? renderPlantUML : undefined,
renderMathJax: config['test'] ? renderMathJax : undefined, renderMathJax: config['test'] ? renderMathJax : undefined,
renderFaDiagrams: config['test'] ? renderFaDiagrams : 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, (data) => { renderPlantUML(data, (data) => {
renderPlantUML(data, (data) => { renderFaDiagrams(data, (data) => {
renderMathJax(data, (data) => { renderMathJax(data, (data) => {
renderShowDown(data, (html) => { renderPrism(data, (data) => {
cb(null, html); renderShowDown(data, (html) => {
cb(null, html);
});
}); });
}); });
}); });
+88 -1
View File
@@ -11,7 +11,8 @@ const config = {
'modules': { 'modules': {
'prism': true, 'prism': true,
'mathjax': true, 'mathjax': true,
'plantuml': true 'plantuml': true,
'fa-diagrams': true,
}, },
'showdown': { 'showdown': {
'simplifiedAutoLink': true, 'simplifiedAutoLink': true,
@@ -32,6 +33,7 @@ beforeEach(() => {
config['modules']['prism'] = true; config['modules']['prism'] = true;
config['modules']['mathjax'] = true; config['modules']['mathjax'] = true;
config['modules']['plantuml'] = true; config['modules']['plantuml'] = true;
config['modules']['fa-diagrams'] = true;
utils.deleteFolderSync(dataDir); utils.deleteFolderSync(dataDir);
fs.mkdirSync(dataDir); fs.mkdirSync(dataDir);
}); });
@@ -42,6 +44,47 @@ afterAll(() => {
} }
}); });
describe('get parts', () => {
test('normal', () => {
const data = 'Hello\nthere\ngeneral\nkenobi';
const parts = renderer.getParts(data);
expect(parts.map(p => p.text)).toEqual([
'Hello\nthere\ngeneral\nkenobi'
]);
});
test('lot of stuff', () => {
const data = 'Hello\nthere\n```code```\ngeneral<script>script</script>\n<script>script2</script>\n```<script>script3</script>```kenobi';
const parts = renderer.getParts(data);
expect(parts).toEqual([
{
index: 0,
end: 12,
text: 'Hello\nthere\n'
},
{
index: 22,
end: 30,
text: '\ngeneral'
},
{
index: 53,
end: 54,
text: '\n'
},
{
index: 78,
end: 79,
text: '\n'
},
{
index: 109,
end: 115,
text: 'kenobi'
},
]);
});
});
describe('Test Showdown', () => { describe('Test Showdown', () => {
test('normal', (done) => { test('normal', (done) => {
renderer.renderShowDown('# Hello', (html) => { renderer.renderShowDown('# Hello', (html) => {
@@ -112,6 +155,13 @@ describe('Test PlantUML', () => {
}); });
}); });
test('plantuml ignored in code', (done) => {
renderer.renderPlantUML('code:\n```@startuml\nBob -> Alice : hello\n@enduml```\n ```@startuml``` @enduml', (data) => {
expect(data).toBe('code:\n```@startuml\nBob -> Alice : hello\n@enduml```\n ```@startuml``` @enduml');
done();
});
});
test('plantuml multiple uml', (done) => { test('plantuml multiple uml', (done) => {
renderer.renderPlantUML('@startuml\nBob -> Alice : hello\n@enduml\n@startuml\nBob -> Alice : hello\n@enduml', (data) => { 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">'); 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">');
@@ -157,6 +207,12 @@ describe('Test MathJax', () => {
done(); done();
}); });
}); });
test('no eq in code / script', (done) => {
renderer.renderMathJax('this code is ```start $a$ end $$hello$$``` beautiful <script>$A$</script>\n```$no eq$```', (data) => {
expect(data).toBe('this code is ```start $a$ end $$hello$$``` beautiful <script>$A$</script>\n```$no eq$```');
done();
});
});
test('multiple eq', (done) => { test('multiple eq', (done) => {
renderer.renderMathJax('$$\n\nA\n\n$$\nstart $a$ end\n$$\n\nA\n\n$$', (data) => { renderer.renderMathJax('$$\n\nA\n\n$$\nstart $a$ end\n$$\n\nA\n\n$$', (data) => {
expect(data).toBe('' + expect(data).toBe('' +
@@ -182,6 +238,37 @@ describe('Test MathJax', () => {
}); });
}); });
describe('Test fa-diagrams', () => {
test('no fa-diagrams', (done) => {
config['modules']['fa-diagrams'] = false;
renderer.renderFaDiagrams('@startfad\noptions.rendering.color=\'red\'\n@endfad', (data) => {
expect(data).toBe('@startfad\noptions.rendering.color=\'red\'\n@endfad');
done();
});
});
test('no fa-diagrams in code', (done) => {
renderer.renderFaDiagrams('code:\n```\n@startfad\noptions.rendering.color=\'red\'\n@endfad\n```', (data) => {
expect(data).toBe('code:\n```\n@startfad\noptions.rendering.color=\'red\'\n@endfad\n```');
done();
});
});
test('valid fa-diagrams', (done) => {
renderer.renderFaDiagrams('before\n@startfad\noptions.rendering.color=\'red\'\n@endfad\nafter', (data) => {
expect(data).toBe('before\n<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 0 0" width="0" height="0" font-family="Arial" font-size="15" fill="red" stroke-width="0"></svg>\nafter');
done();
});
});
test('invalid toml', (done) => {
renderer.renderFaDiagrams('before\n@startfad\noptions.rendering.color=red\n@endfad\nafter', (data) => {
expect(data).toBe('before\n<b style="color:red">TomlError: Unexpected character, expecting string, number, datetime, boolean, inline array or inline table at row 1, col 26, pos 25:\n' +
'1> options.rendering.color=red\n' +
' ^\n' +
'\n</b>\nafter');
done();
});
});
});
describe('Test render', () => { describe('Test render', () => {
test('invalid file', (done) => { test('invalid file', (done) => {
renderer.render('invalid file', (err, html) => { renderer.render('invalid file', (err, html) => {
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 20 KiB

+2
View File
@@ -10,6 +10,7 @@ node nodejs {
} }
package data { package data {
[template.ejs]
package "2019/06/18" { package "2019/06/18" {
component index [ component index [
index.md index.md
@@ -22,6 +23,7 @@ package data {
web -down-> TCP : 1. /2019/06/18/title web -down-> TCP : 1. /2019/06/18/title
express -down-> index : 2. fetch express -down-> index : 2. fetch
index -up-> showdown : 3. markdown index -up-> showdown : 3. markdown
template.ejs -up-> express : 4
showdown -left-> express : 4. html showdown -left-> express : 4. html
express -up-> web : 5. html express -up-> web : 5. html