Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support PlantUML; Ordering in [[index]] #37

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 51 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
- In-browser editor
- Table of contents using Markdown extension `[[toc]]`
- Navigation index using Markdown extension `[[index]]`
- Diagrams and flowcharts using [Mermaid](http://knsv.github.io/mermaid/) syntax
- Diagrams and flowcharts using [Mermaid](http://knsv.github.io/mermaid/) and [PlantUML](http://plantuml.com/) syntax
- Drag'n drop images
- 100% offline
- Custom CSS style
Expand Down Expand Up @@ -74,10 +74,17 @@ specified *root dir*. File and folder names will be *humanized* for better reada

It is particularly useful on the home page to provide an overview of the available documentation for your project.

### Diagrams and flowcharts
The sorting of each index level is as follows:
1. Any README.md, readme.md, or index.md is always at the top.
2. All files and folders that are prefixed with a number (e.g. `001-abc` and `002 mno` and `003_xyz`) are next, sorted
by their respective prefix numbers. Note that the prefix numbers are stripped out in the index.
3. All remaining files, sorted by their name.
4. All remaining folders, sorted by their name.

### Mermaid Diagrams and flowcharts

You can use the [Mermaid](http://knsv.github.io/mermaid/) syntax to insert diagrams and flowcharts directly in your
markdown, but using code blocks with the `mermaid` language specified, like this:
markdown, by using code blocks with the `mermaid` language specified, like this:

```mermaid
graph TD;
Expand All @@ -95,6 +102,47 @@ MERMAID_CONFIG = { theme: 'forest' };
</script>
```

### PlantUML Diagrams

You can use the [PlantUML](http://plantuml.com/) syntax to insert diagrams and flowcharts directly in your
markdown, by using code blocks with the `plantuml` or `puml` language specified, like this:

```plantuml
@startuml
Alice -> Bob: Authentication Request
Bob --> Alice: Authentication Response

Alice -> Bob: Another authentication Request
Alice <-- Bob: Another authentication Response
@enduml
```

or


```puml
@startgantt
[Prototype design] lasts 15 days
[Test prototype] lasts 10 days
@endgantt
```

Since PlantUML uses Graphviz/DOT, it is also possible to directly use the DOT language.


```puml
@startdot
digraph foo {
node [style=rounded]
node1 [shape=box]
node2 [fillcolor=yellow, style="rounded,filled", shape=diamond]
node3 [shape=record, label="{ a | b | c }"]

node1 -> node2 -> node3
}
@enddot
```

## Updates

See changelog [here](CHANGELOG.md)
20 changes: 20 additions & 0 deletions hads.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ const multer = require('multer');
const bodyParser = require('body-parser');
const shortId = require('shortid');
const moment = require('moment');
const plantuml = require('node-plantuml-vizjs');
const LZString = require('lz-string');
const pkg = require('./package.json');
const Matcher = require('./lib/matcher.js');
const Renderer = require('./lib/renderer.js');
Expand Down Expand Up @@ -96,6 +98,24 @@ const STYLESHEETS = [
'/font-awesome/css/font-awesome.css'
].concat(hasCustomCss ? [`/${customCssFile}`] : []);

app.get('/_hads/plantuml/png/:uml', (req, res) => {
res.set('Content-Type', 'image/png');

const decode = LZString.decompressFromEncodedURIComponent(req.params.uml);
const gen = plantuml.generate(decode, {format: 'png'});

gen.out.pipe(res);
});

app.get('/_hads/plantuml/svg/:uml', (req, res) => {
res.set('Content-Type', 'image/svg+xml');

const decode = LZString.decompressFromEncodedURIComponent(req.params.uml);
const gen = plantuml.generate(decode, {format: 'svg'});

gen.out.pipe(res);
});

app.get('*', (req, res, next) => {
let route = Helpers.extractRoute(req.path);
const query = req.query || {};
Expand Down
83 changes: 79 additions & 4 deletions lib/renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,19 @@ const marked = require('marked');
const highlight = require('highlight.js');
const removeMd = require('remove-markdown');
const humanize = require('string-humanize');
const LZString = require('lz-string');

const SEARCH_EXTRACT_LENGTH = 400;
const SEARCH_RESULTS_MAX = 10;

const ROOT_FILES_INDEX = {
'index.md': true,
'README.md': true,
'readme.md': true
};

const WORD_SEPARATORS = /[-_\s]/g;

class Renderer {
constructor(indexer) {
this.indexer = indexer;
Expand Down Expand Up @@ -100,10 +109,17 @@ class Renderer {
renderMarkdown(content) {
const renderer = new marked.Renderer();
renderer.code = (code, language) => {
let retVal;
if (language === 'mermaid') {
return `<p class="mermaid">${code}</p>`;
retVal = `<p class="mermaid">${code}</p>`;
} else if (language === 'puml' || language === 'plantuml') {
const encodedPuml = LZString.compressToEncodedURIComponent(code);
retVal = `<object data="/_hads/plantuml/svg/${encodedPuml}" type="image/svg+xml"><img src="/_hads/plantuml/png/${encodedPuml}" /></object>`;
} else {
retVal = marked.Renderer.prototype.code.call(renderer, code, language);
}
return marked.Renderer.prototype.code.call(renderer, code, language);

return retVal;
};
renderer.paragraph = text => {
text = text.replace(/^\[\[toc]]/img, () => this.renderTableOfContents(content));
Expand Down Expand Up @@ -142,9 +158,33 @@ class Renderer {
const keys = Object.keys(index).sort((a, b) => {
const aType = typeof index[a];
const bType = typeof index[b];
const aNumPrefix = Renderer.getNumberPrefix(a);
const bNumPrefix = Renderer.getNumberPrefix(b);

if (ROOT_FILES_INDEX[a]) {
return -1;
}

if (ROOT_FILES_INDEX[b]) {
return 1;
}

if (Number.isFinite(aNumPrefix) && Number.isFinite(bNumPrefix)) {
return aNumPrefix - bNumPrefix;
}

if (Number.isFinite(aNumPrefix)) {
return -1;
}

if (Number.isFinite(bNumPrefix)) {
return 1;
}

if (aType === bType) {
return a.localeCompare(b);
}

if (aType === 'string') {
// Display files before folders
return -1;
Expand All @@ -158,15 +198,50 @@ class Renderer {

if (typeof value === 'string') {
key = path.basename(key, path.extname(key));
content += `- [${humanize(key)}](/${value})\n`;
content += `- [${humanize(Renderer.trimNumberPrefix(key))}](/${encodeURI(value)})\n`;
} else {
content += `- ${humanize(key)}\n`;
content += `- ${humanize(Renderer.trimNumberPrefix(key))}\n`;
content += Renderer.renderIndexLevel(value, level + 1);
}
});

return content;
}

/**
* Removes the numbered prefix like the 000 in 000-xyz.
*
* @param key
*/
static trimNumberPrefix(key) {
const split = key.split(WORD_SEPARATORS);
if (split && split.length > 1) { // First item is a number prefix, second+ item is the name.
const num = parseInt(split[0], 10);
if (Number.isFinite(num)) {
return key.substring(key.indexOf(split[1]));
}
}

return key;
}

/**
* Whether the key has a number prefix like 000-xyz.
*
* @param key
* @returns {number}
*/
static getNumberPrefix(key) {
const split = key.split(WORD_SEPARATORS);
if (split && split.length > 1) { // First item is a number prefix, second+ item is the name.
const num = parseInt(split[0], 10);
if (Number.isFinite(num)) {
return num;
}
}

return NaN;
}
}

module.exports = Renderer;
58 changes: 57 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "hads",
"version": "1.7.0",
"version": "1.8.0",
"description": "Fast web server allowing to browse, search and edit project documentation written in Markdown",
"repository": {
"type": "git",
Expand Down Expand Up @@ -50,11 +50,13 @@
"font-awesome": "^4.7.0",
"highlight.js": "^9.12.0",
"lodash": "^4.17.10",
"lz-string": "^1.4.4",
"marked": "^0.4.0",
"mermaid": "^7.1.2",
"mkdirp": "^0.5.1",
"moment": "^2.22.2",
"multer": "^1.3.1",
"node-plantuml-vizjs": "^0.7.0",
"octicons": "^4.4.0",
"opn": "^5.3.0",
"optimist": "^0.6.1",
Expand Down
3 changes: 3 additions & 0 deletions test/001 first folder/some doc.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Some Doc

Hello
File renamed without changes.
Loading