Difference between revisions of "Diagrams"
| (20 intermediate revisions by the same user not shown) | |||
| Line 2: | Line 2: | ||
|id=diagrams | |id=diagrams | ||
|owner=BITPlan | |owner=BITPlan | ||
| − | |title= | + | |state=active |
| + | |title=online-diagrams | ||
| + | |description=online diagrams rendering service for graphviz, mscgen and plantuml | ||
|url=https://github.com/BITPlan/diagrams | |url=https://github.com/BITPlan/diagrams | ||
| − | |date=2020-02-14 | + | |date=2023-10-28 |
| − | |version=0.0 | + | |since=2020-02-14 |
| + | |version=0.1.0 | ||
| + | }} | ||
{{:Diagrams/Links}} | {{:Diagrams/Links}} | ||
= What is it ? = | = What is it ? = | ||
| Line 40: | Line 44: | ||
|- | |- | ||
| neato | | neato | ||
| − | |<pre>graph G { | + | |<pre><graphviz renderer='neato'> |
| + | graph G { | ||
run -- intr; | run -- intr; | ||
intr -- runbl; | intr -- runbl; | ||
| Line 55: | Line 60: | ||
sleep -- runmem; | sleep -- runmem; | ||
} | } | ||
| + | </graphviz> | ||
</pre> | </pre> | ||
|<graphviz renderer='neato'> | |<graphviz renderer='neato'> | ||
| Line 81: | Line 87: | ||
git clone https://github.com/BITPlan/diagrams | git clone https://github.com/BITPlan/diagrams | ||
cd diagrams | cd diagrams | ||
| − | + | scripts/install | |
</source> | </source> | ||
| + | |||
= Running = | = Running = | ||
== Usage == | == Usage == | ||
| Line 103: | Line 110: | ||
</source> | </source> | ||
By default the webservice will be available on port 5003. | By default the webservice will be available on port 5003. | ||
| + | == trying == | ||
| + | You might want to adapt the url "https://diagrams.bitplan.com" to your webserver's url e.g. "http://localhost:5003" | ||
| + | <source lang='bash' highlight='1'> | ||
| + | curl -X POST -F 'generator=plantuml' -F source='version' https://diagrams.bitplan.com/render | ||
| + | </source> | ||
| + | should return | ||
| + | <source lang='json'> | ||
| + | { | ||
| + | "diagrams": { | ||
| + | "png": { | ||
| + | "url": "https://diagrams.bitplan.com/render/png/0x97cd3329.png" | ||
| + | } | ||
| + | } | ||
| + | </source> | ||
| + | [https://diagrams.bitplan.com/render/png/0x97cd3329.png <nowiki>https://diagrams.bitplan.com/render/png/0x97cd3329.png</nowiki>] containing: | ||
| + | https://diagrams.bitplan.com/render/png/0x97cd3329.png | ||
| + | |||
| + | = MediaWiki Diagrams extension = | ||
| + | The webservice can be used as endpoint for the [https://www.mediawiki.org/wiki/Extension:Diagrams the MediaWiki diagrams extension] | ||
| + | {{Extension | ||
| + | |name=Diagrams | ||
| + | |url=https://www.mediawiki.org/wiki/Extension:Diagrams | ||
| + | |purpose=Replaces deprecated | ||
| + | https://www.mediawiki.org/wiki/Extension:GraphViz and | ||
| + | https://www.mediawiki.org/wiki/Extension:PlantUML | ||
| + | extensions | ||
| + | |since=2019/12/12 | ||
| + | |storemode=property | ||
| + | }} | ||
| + | |||
| + | = Installation = | ||
| + | <source lang='bash'> | ||
| + | git clone https://github.com/samwilson/diagrams-extension Diagrams | ||
| + | wfLoadExtension( 'Diagrams' ); | ||
| + | // The URL at which you installed the Diagrams Service. | ||
| + | $wgDiagramsServiceUrl = 'http://diagrams.bitplan.com'; | ||
| + | </source> | ||
| + | |||
| + | == Install the extension == | ||
| + | <source lang='bash'> | ||
| + | cd extensions | ||
| + | git clone https://github.com/samwilson/diagrams-extension.git Diagrams | ||
| + | Cloning into 'Diagrams'... | ||
| + | </source> | ||
| + | == Loading extension == | ||
| + | in LocalSettings.php add | ||
| + | <source lang='php'> | ||
| + | $wgDiagramsServiceUrl ='https://diagrams.bitplan.com'; | ||
| + | wfLoadExtension( 'Diagrams' ); | ||
| + | </source> | ||
| + | replacing the $wgDiagramsServiceUrl with your own webservice to improve performance | ||
| + | |||
| + | == MediaWiki 1.33.4 workaround == | ||
| + | === Hooks.php === | ||
| + | <source lang='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); | ||
| + | $generator=$tag; | ||
| + | switch ($tag) { | ||
| + | case 'graphviz': $format='cmapx';break; | ||
| + | case 'mscgen' : $format='ismap';break; | ||
| + | case 'uml': $format='png';$generator='plantuml'; break; | ||
| + | default: $format="png"; | ||
| + | } | ||
| + | if (isset($args["format"])) { | ||
| + | $format=$args["format"]; | ||
| + | $logger->debug("log format=".$format); | ||
| + | } | ||
| + | // Make sure there's something to render. | ||
| + | $input = trim( $input ); | ||
| + | if ( $input === '' ) { | ||
| + | return ''; | ||
| + | } | ||
| + | return static::render( $generator, $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) { | ||
| + | $baseUrl = MediaWikiServices::getInstance()->getMainConfig()->get( 'DiagramsServiceUrl' ); | ||
| + | $url = trim( $baseUrl, '/' ) . '/render'; | ||
| + | # log debug information | ||
| + | $logger = LoggerFactory::getInstance( 'Diagrams' ); | ||
| + | $logger->debug("url=".$url); | ||
| + | $logger->debug("generator=".$generator); | ||
| + | $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 ); | ||
| + | } | ||
| + | } | ||
| + | </source> | ||
= MediaWiki Diagrams Extension Json API = | = MediaWiki Diagrams Extension Json API = | ||
Latest revision as of 12:44, 28 October 2023
| OsProject | |
|---|---|
| id | diagrams |
| state | active |
| owner | BITPlan |
| title | online-diagrams |
| url | https://github.com/BITPlan/diagrams |
| version | 0.1.0 |
| description | online diagrams rendering service for graphviz, mscgen and plantuml |
| date | 2023-10-28 |
| since | 2020-02-14 |
| 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.
trying
You might want to adapt the url "https://diagrams.bitplan.com" to your webserver's url e.g. "http://localhost:5003"
curl -X POST -F 'generator=plantuml' -F source='version' https://diagrams.bitplan.com/render
should return
{
"diagrams": {
"png": {
"url": "https://diagrams.bitplan.com/render/png/0x97cd3329.png"
}
}
https://diagrams.bitplan.com/render/png/0x97cd3329.png containing:
MediaWiki Diagrams extension
The webservice can be used as endpoint for the the MediaWiki diagrams extension
| Extension | |
|---|---|
| name | Diagrams |
| url | https://www.mediawiki.org/wiki/Extension:Diagrams |
| purpose | Replaces deprecated
https://www.mediawiki.org/wiki/Extension:GraphViz and https://www.mediawiki.org/wiki/Extension:PlantUML extensions |
| since | 2019/12/12 |
| wiki | |
Installation
git clone https://github.com/samwilson/diagrams-extension Diagrams
wfLoadExtension( 'Diagrams' );
// The URL at which you installed the Diagrams Service.
$wgDiagramsServiceUrl = 'http://diagrams.bitplan.com';
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);
$generator=$tag;
switch ($tag) {
case 'graphviz': $format='cmapx';break;
case 'mscgen' : $format='ismap';break;
case 'uml': $format='png';$generator='plantuml'; break;
default: $format="png";
}
if (isset($args["format"])) {
$format=$args["format"];
$logger->debug("log format=".$format);
}
// Make sure there's something to render.
$input = trim( $input );
if ( $input === '' ) {
return '';
}
return static::render( $generator, $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) {
$baseUrl = MediaWikiServices::getInstance()->getMainConfig()->get( 'DiagramsServiceUrl' );
$url = trim( $baseUrl, '/' ) . '/render';
# log debug information
$logger = LoggerFactory::getInstance( 'Diagrams' );
$logger->debug("url=".$url);
$logger->debug("generator=".$generator);
$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"
}




