Diagrams
OsProject | |
---|---|
id | diagrams |
state | |
owner | BITPlan |
title | Diagrams rendering service for graphviz, mscgen and plantuml |
url | https://github.com/BITPlan/diagrams |
version | 0.0.1 |
description | |
date | 2020-02-14 |
since | |
until |
Click here to comment see Diagrams
What is it ?
This is a Python based webservice to render diagrams for
Demo
Examples
tool | source | image |
---|---|---|
dot | <graphviz> graph development { Stakeholder -- Requirements; Requirements -- Samplecases; Requirements -- Model; Model -- Code; } </graphviz> |
|
neato | <graphviz renderer='neato'> graph G { run -- intr; intr -- runbl; runbl -- run; run -- kernel; kernel -- zombie; kernel -- sleep; kernel -- runmem; sleep -- swap; swap -- runswap; runswap -- new; runswap -- runmem;n new -- runmem; sleep -- runmem; } </graphviz> |
Installation
If you'd like to run your own service you need a python 3 environment includin pip3. The software has been tested on Ubuntu 18.04 and Mac OS 13.6 using macports.
git clone https://github.com/BITPlan/diagrams
cd diagrams
scripts/install
Running
Usage
python3 dgs/webserver.py -h
usage: webserver.py [-h] [--debug] [--port PORT] [--host HOST]
Diagrams rendering webservice
optional arguments:
-h, --help show this help message and exit
--debug run in debug mode
--port PORT the port to use
--host HOST the host to serve for
starting webservice
export PYTHONPATH="."
python3 dgs/webserver.py
By default the webservice will be available on port 5003.
MediaWiki Diagrams extension
The webservice can be used as endpoint for the the MediaWiki diagrams extension
Install the extension
cd extensions
git clone https://github.com/samwilson/diagrams-extension.git Diagrams
Cloning into 'Diagrams'...
Loading extension
in LocalSettings.php add
$wgDiagramsServiceUrl ='https://diagrams.bitplan.com';
wfLoadExtension( 'Diagrams' );
replacing the $wgDiagramsServiceUrl with your own webservice to improve performance
MediaWiki 1.33.4 workaround
Hooks.php
<?php
namespace MediaWiki\Extension\Diagrams;
use Html;
use Http;
use MediaWiki\MediaWikiServices;
use Parser;
use MediaWiki\Logger\LoggerFactory;
class Hooks {
/**
* @see https://www.mediawiki.org/wiki/Manual:Hooks/ParserFirstCallInit
* @param Parser $parser
*/
public static function onParserFirstCallInit( Parser $parser ) {
foreach ( [ 'graphviz', 'mscgen', 'uml' ] as $tag ) {
$parser->setHook( $tag, function ( string $input, array $args) use ( $tag ) {
$logger = LoggerFactory::getInstance( 'Diagrams' );
$logger->debug("tag=".$tag);
if (isset($args["format"])) {
$format=$args["format"];
$logger->debug("log format=".$format);
} else {
$format="png";
}
// Make sure there's something to render.
$input = trim( $input );
if ( $input === '' ) {
return '';
}
if ( $tag === 'graphviz' ) {
// GraphViz.
return static::render( $tag, $input, 'cmapx' );
} elseif ( $tag === 'mscgen' ) {
// Mscgen.
return static::render( $tag, $input, 'ismap' );
} else {
// PlantUML.
return static::render( 'plantuml', $input, $format );
}
} );
}
}
/**
* Get HTML for an error message.
* @param string $error Error message. May contain HTML.
* @return string
*/
protected static function formatError( $error ) {
return Html::rawElement( 'span', [ 'class' => 'ext-diagrams error' ], $error );
}
/**
* The main rendering method, handling all types.
* @param string $generator
* @param string $input
* @param string $format
* @return string
*/
protected static function render( $generator, $input, $format = null ) {
$baseUrl = MediaWikiServices::getInstance()->getMainConfig()->get( 'DiagramsServiceUrl' );
$url = trim( $baseUrl, '/' ) . '/render';
$logger = LoggerFactory::getInstance( 'Diagrams' );
$logger->debug("url=".$url);
$logger->debug("format=".$format);
$params = [
'postData' => http_build_query( [
'generator' => $generator,
'types' => $format,
'source' => $input,
] ),
];
$result = Http::request( 'POST', $url, $params, __METHOD__ );
if ( $result === false ) {
return static::formatError( wfMessage( 'diagrams-error-no-response' ) );
}
$response = json_decode( $result );
if ( isset( $response->error ) ) {
$error = wfMessage( 'diagrams-error-returned-' . $response->error );
if ( isset( $response->message ) ) {
$error .= Html::element( 'br' ) . $response->message;
}
return static::formatError( $error );
}
if ( isset( $response->diagrams->cmapx->contents ) ) {
// Image maps in cmapx format.
$imageMap = new ImageMap( $response->diagrams->cmapx->contents );
if ( $imageMap->hasAreas() ) {
$imgAttrs['usemap'] = '#' . $imageMap->getName();
}
$out = Html::element( 'img', $imgAttrs );
if ( $imageMap->hasAreas() ) {
$out .= $imageMap->getMap();
}
} elseif ( isset( $response->diagrams->ismap->contents ) ) {
// Image maps in imap format.
$imgAttrs['ismap'] = true;
$out = Html::rawElement(
'a',
[ 'href' => $response->diagrams->ismap->url ],
Html::element( 'img', $imgAttrs )
);
} else {
// No image map. - plain format
switch ($format) {
case 'svg':
$objectAttrs= [ 'data' => $response->diagrams->svg->url, type=>'image/svg+xml'];
$out = Html::rawElement(
'object',
$objectAttrs
);
break;
default:
$imgAttrs = [ 'src' => $response->diagrams->png->url ];
$out = Html::element( 'img', $imgAttrs );
}
}
return Html::rawElement( 'div', [ 'class' => 'ext-diagrams' ], $out );
}
}
MediaWiki Diagrams Extension Json API
The communication between the MediaWiki diagrams extension and this webservice is done with POST requests that expect Json responses.
Diagrams
Example
{
"diagrams": {
"png": {
"url": "http://diagrams.bitplan.com/render/png/0xb00d69ad"
}
}
}
Errors
Example
{
"error": "service not ready",
"message": "not implemented yet"
}