This commit is contained in:
Andy Bunce 2013-01-20 23:37:18 +00:00
parent 3aa4cb7757
commit 63c8f5d0a9
10 changed files with 147 additions and 105 deletions

18
src/graphxq/dotml.xqm Normal file
View File

@ -0,0 +1,18 @@
(:~
: dotml module
: @see http://www.martin-loetzsch.de/DOTML/
:)
module namespace dotml="http://www.martin-loetzsch.de/DOTML";
declare default function namespace 'http://www.martin-loetzsch.de/DOTML';
import module namespace xslt="http://basex.org/modules/xslt";
(:~
: @return graphviz dot string
:)
declare function generate($dotml) as xs:string
{
xslt:transform($dotml, fn:resolve-uri( "dotml/dotml2dot.xsl"))
};

View File

@ -1,11 +1,10 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml" xmlns:dotml="http://www.martin-loetzsch.de/DOTML">
<!--
File dotml2dot.xsl
Copyright 2002 - 2006 Martin Loetzsch
Translates dotml documents into the native dot syntax.
-->
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml" xmlns:dotml="http://www.martin-loetzsch.de/DOTML">
<xsl:output method="text"/>
<xsl:variable xml:space="preserve" name="graph-attributes">bgcolor fontcolor fontname fontsize label margin nodesep rankdir ranksep ratio size</xsl:variable>
<xsl:variable xml:space="preserve" name="cluster-attributes">bgcolor color fillcolor fontcolor fontname fontsize label labeljust labelloc style</xsl:variable>
<xsl:variable xml:space="preserve" name="node-attributes">color fillcolor fixedsize fontcolor fontname fontsize height shape style URL width</xsl:variable>
@ -16,12 +15,11 @@ Translates dotml documents into the native dot syntax.
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="text()"/>
<xsl:template match="dotml:graph">digraph g {compound="true";<xsl:call-template name="copy-attributes">
<xsl:template match="dotml:graph"><dummy>digraph g {compound="true";<xsl:call-template name="copy-attributes">
<xsl:with-param name="separator" select="';'"/>
<xsl:with-param name="attributes" select="$graph-attributes"/>
</xsl:call-template>
<xsl:apply-templates/>}
&lt;dot-filename&gt;<xsl:value-of select="@file-name"/>&lt;/dot-filename&gt;
<xsl:apply-templates/>}</dummy>
</xsl:template>
<xsl:template match="dotml:sub-graph">subgraph sub_graph_<xsl:value-of select="count(preceding::dotml:sub-graph)"/>{rank="<xsl:value-of select="@rank"/>";<xsl:apply-templates/>}</xsl:template>
<xsl:template match="dotml:cluster">subgraph cluster_<xsl:value-of select="@id"/>{<xsl:call-template name="copy-attributes">

View File

@ -38,7 +38,8 @@ declare function dot( $dot as xs:string*, $params as xs:string*) as node()*{
else $gr:empty
};
declare %private function dot1( $dot as xs:string) as node(){
declare %private function dot1( $dot as xs:string) as element(svg:svg)
{
let $fname:=$gr:tmpdir || random:uuid()
let $junk:=file:write-text($fname,$dot)
let $r:=proc:execute($gr:dotpath , ("-Tsvg",$fname))
@ -77,6 +78,7 @@ declare %private function dot1( $dot as xs:string) as node(){
</svg>
};
(:~
:Layout one ore more graphs given in the GXL language and render them as SVG.
: gxl2dot Test.gxl > Test.dot

View File

@ -1,5 +1,5 @@
(:~
: restxq interface for graphviz
: RESTXQ interface for graphviz
: @author andy bunce
: @since sept 2012
:)
@ -8,13 +8,19 @@ module namespace grxq = 'apb.graphviz.web';
declare default function namespace 'apb.graphviz.web';
import module namespace gr = 'apb.graphviz' at "graphviz.xqm";
import module namespace dotml = 'http://www.martin-loetzsch.de/DOTML' at "dotml.xqm";
import module namespace dotui = 'apb.graphxq.dotui' at "dotui.xqm";
import module namespace txq = 'apb.txq' at "lib/txq.xqm";
import module namespace request = "http://exquery.org/ns/request";
declare namespace svg= "http://www.w3.org/2000/svg";
declare namespace rest = 'http://exquery.org/ns/restxq';
declare variable $grxq:layout:=fn:resolve-uri("views/layout.xml");
(:~
: Home page for app
:)
declare
%rest:GET %rest:path("graphxq")
%output:method("html") %output:version("5.0")
@ -23,14 +29,14 @@ declare
function graphxq($dot,$url) {
let $edot:=if($url) then "" else fn:encode-for-uri($dot)
let $dot2:=getdot($dot,$url)
let $svg:=get-svg($dot)
let $map:=map{"dot":=$dot,"url":=$url,"svg":=$svg,"edot":=$edot}
let $page:=render("views/page1.xml",$map)
return $page
let $svg:=dot2svg($dot)
let $map:=map{"dot":=$dot,"url":=$url,"svg":=$svg,"edot":=$edot}
let $page:=render("views/page1.xml",$map)
return $page
};
(:~
: return svg for dot, with download option
: GET or POST return svg for dot, with download option
:)
declare
%rest:path("graphxq/svg")
@ -39,18 +45,18 @@ declare
%rest:form-param("dl","{$dl}")
%output:media-type("image/svg+xml")
function graphxq-svg($dot,$url,$dl) {
let $dot2:=getdot($dot,$url)
let $svg:=get-svg($dot2)
let $resp:=<rest:response>
<http:response>
<http:header name="Access-Control-Allow-Origin" value="*"/>
{if($dl)
then <http:header name="Content-Disposition" value='attachment;filename="graphxq.svg"'/>
else ()}
</http:response>
</rest:response>
let $dot2:=getdot($dot,$url)
let $svg:=dot2svg($dot2)
let $resp:=<rest:response>
<http:response>
<http:header name="Access-Control-Allow-Origin" value="*"/>
{if($dl)
then <http:header name="Content-Disposition" value='attachment;filename="graphxq.svg"'/>
else ()}
</http:response>
</rest:response>
return ($resp,$svg)
return ($resp,$svg)
};
(:~
@ -64,25 +70,34 @@ declare
function dotform($src){
let $dot:= getdot("digraph {{a -> b}}",$src)
let $svgwidget:=fn:doc("views/widget.svg")
let $map:=map{"list-shapes":=dotui:shapes(""),
"list-colors":=dotui:colors(""),
"svgwidget":=$svgwidget,
"dot":=$dot}
return render("views/dotform.xml",$map)
let $map:=map{"list-shapes":=dotui:shapes(""),
"list-colors":=dotui:colors(""),
"svgwidget":=$svgwidget,
"dot":=$dot}
return render("views/dotform.xml",$map)
};
declare
%rest:GET %rest:path("graphxq/dotml")
%output:method("html") %output:version("5.0")
function dotmlform(){
render("views/dotmlform.xml",map{})
render("views/dotmlform.xml",map{})
};
(:~ static about page :)
declare
%rest:GET %rest:path("graphxq/about")
%output:method("html") %output:version("5.0")
function about(){
render("views/about.xml",map{})
render("views/about.xml",map{})
};
(:~ static api page :)
declare
%rest:GET %rest:path("graphxq/api")
%output:method("html") %output:version("5.0")
function api(){
render("views/api.xml",map{})
};
declare
@ -93,44 +108,72 @@ function search($q ) {
let $map:=map{"q":=$q}
return render("views/search.xml",$map)
};
declare
%rest:GET %rest:path("graphxq/library")
%output:method("html") %output:version("5.0")
function library( ) {
let $map:=map{ }
return render("views/library.xml",$map)
};
(:~
: @return svg from dotml
:)
declare
%rest:POST %rest:path("graphxq/api/dotml")
%rest:form-param("dotml","{$dotml}")
function api-dotml($dotml ) as node()
{
let $dotml:=fn:parse-xml($dotml)
let $x:=dotml:generate($dotml)
(: let $svg:=dot2svg($x) :)
return $x
(:~ use dot or url :)
declare %private function getdot($dot,$url) as xs:string{
};
(:~ if url is defined then treat as url and fetch else use dot :)
declare %private function getdot($dot as xs:string,$url) as xs:string{
if($url) then
try{fn:unparsed-text(fn:resolve-uri($url))} catch * { "digraph {{ failed to load remote }}" }
else
$dot
};
(:~ post process svg :)
declare %private function get-svg($dot as xs:string) as node(){
(:~ if url is defined then treat as url and fetch else use dotml :)
declare %private function getdotml($dotml as xs:string,$url) as xs:string{
if($url) then
try{fn:unparsed-text(fn:resolve-uri($url))} catch * { "digraph {{ failed to load remote }}" }
else
$dotml
};
(:~ Generate svg from dot :)
declare %private function dot2svg($dot as xs:string) as node(){
let $svgx:=gr:dot($dot,())
return gr:autosize($svgx)
};
declare function render($template,$locals){
(:~
: Render html page
: @param template path to page template
: @params locals map of page variables
:)
declare function render($template as xs:string,$locals){
let $sidebar:=<div>
<a href="/graphxq/viewbox/viewBox.svg">viewbox work</a>
<ul>
<div>Samples:</div>
<li> <a href="dot?src=samples/dot/process.gv">process</a></li>
<li><a href="/restxq/graphxq/dot?src=samples/dot/unix.gv">unix</a></li>
<li> <a href="/restxq/graphxq/dot?src=samples/dot/root.gv">root (slow)</a></li>
</ul>
<a href="/graphxq/viewbox/viewBox.svg">viewbox work</a>
<ul>
<div>Samples:</div>
<li> <a href="dot?src=samples/dot/process.gv">process</a></li>
<li><a href="dot?src=samples/dot/unix.gv">unix</a></li>
<li><a href="dot?src=samples/dot/root.gv">root (slow)</a></li>
<li><a href="dotml?src=samples/dotml/sample1.xml">dotml sample</a></li>
</ul>
</div>
let $default:=map{"sidebar":=$sidebar ,
let $default:=map{"sidebar":=$sidebar ,
"usermenu":=<div>users</div>,
"title":=request:path(),
"messages":=()}
let $locals:=map:new(($default,$locals))
return txq:render(fn:resolve-uri($template),$locals,$grxq:layout)
"messages":=()}
let $locals:=map:new(($default,$locals))
return txq:render(fn:resolve-uri($template),$locals,$grxq:layout)
};

View File

@ -1,4 +1,4 @@
<graph file-name="graphs/example_xabsl_option1" ranksep="0.3" nodesep="0.2">
<graph xmlns="http://www.martin-loetzsch.de/DOTML" ranksep="0.3" nodesep="0.2">
<cluster id="option" label="option handle-ball-at-left-and-right-border" fontname="Arial" fontcolor="#005A9C" fontsize="11" fillcolor="#F4F4F4" style="filled">
<sub-graph rank="same">
<node label="go\nto\nball" fontcolor="#005A9C" fontsize="11" style="filled" fillcolor="#FFFFFF" fontname="Arial" id="state_go_to_ball" shape="Mcircle"/>

View File

@ -1,46 +0,0 @@
(:~
: A(nother) templating Engine for XQuery (BaseX 7.5+(or -) specific)
:
: @author andy bunce
: @since sept 2012
:)
module namespace txq = 'apb.txq';
declare default function namespace 'apb.txq';
import module namespace xquery = "http://basex.org/modules/xquery";
(:~
: template function
: @return updated doc from map
:)
declare function render($map as map(*),$layout as xs:string,$file as xs:string)
{
let $content:=render($map,$file)
let $map:=map:new(($map,map{"body":=$content}))
return render($map,$layout)
};
(:~
: template function
: @return updated doc from map
:)
declare function render($layout as xs:string,$map as map(*))
{
let $map:=map:new(($map,map{"partial":=partial(?,?,?,$map,$layout)}))
return xquery:invoke($layout,$map)
};
(:~
: partial template function: evaluate part for each value in sequence
: @return updated doc from map
:)
declare function partial($part as xs:string,$name,$seq,$map,$base)
{
for $s in $seq
let $map:=map:new(($map,map{$name:=$s}))
return render($map,fn:resolve-uri($part,$base))
};

View File

@ -42,7 +42,7 @@
<li class="tweet-btn"><iframe title="Twitter Tweet Button"
style="width: 106px; height: 20px;"
class="twitter-share-button twitter-count-horizontal"
src="http://platform.twitter.com/widgets/tweet_button.html?count=horizontal&amp;id=twitter-widget-0&amp;lang=en&amp;original_referer=https%3A%2F%2Fgithub.com%2Fapb2006%2Fxqwebdoc%2F&amp;size=m&amp;text=xqwebdoc #xquery&amp;url=https%3A%2F%2Fgithub.com%2Fapb2006%2Fxqwebdoc&amp;via=apb1704"
src="http://platform.twitter.com/widgets/tweet_button.html?count=horizontal&amp;id=twitter-widget-0&amp;lang=en&amp;original_referer=https%3A%2F%2Fgithub.com%2Fapb2006%2Fgraphxq&amp;size=m&amp;text=graphxq #xquery&amp;url=https%3A%2F%2Fgithub.com%2Fapb2006%2Fxqwebdoc&amp;via=apb1704"
allowtransparency="true" scrolling="no" frameborder="0"></iframe></li>
</ul>
</div>

View File

@ -0,0 +1,7 @@
<div>
<h1>About GraphXQ API</h1>
<p>
POST or GET <div>restxq/svg?dot=..</div>
</p>
</div>

View File

@ -1,8 +1,17 @@
<div class="row-fluid" style="heigth:20em">
<div class="row-fluid" style="height:20em">
<div class="span5">
<form method="post" action="." style="background-color:#EEEEEE;padding:8px;">
<form method="post" action="api/dotml" style="background-color:#EEEEEE;padding:8px;">
<textarea name="dot" rows="2" cols="80"></textarea>
<textarea name="dotml" rows="12" cols="80">
&lt;graph file-name=&quot;graphs/decorate&quot;&gt;
&lt;node id=&quot;a&quot;/&gt;
&lt;node id=&quot;b&quot;/&gt;
&lt;node id=&quot;c&quot;/&gt;
&lt;edge from=&quot;a&quot; to=&quot;c&quot; decorate=&quot;false&quot; label=&quot;decorate=&#39;false&#39;&quot;/&gt;
&lt;edge from=&quot;b&quot; to=&quot;c&quot; decorate=&quot;true&quot; label=&quot;decorate=&#39;true&#39;&quot;/&gt;
&lt;/graph&gt;
</textarea>
<button type="submit">Redraw</button>
</form >

View File

@ -5,7 +5,7 @@
<base href="/restxq/graphxq/" />
<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="xquery documentation" />
<meta name="description" content="graphviz tool" />
<meta name="author" content="andy bunce" />
<link href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/2.2.2/css/bootstrap.css" rel="stylesheet"
type="text/css" />
@ -63,11 +63,22 @@
</li>
</ul>
</li>
<li class="nav">
<li >
<a href="library">Library</a>
</li>
<li class="nav">
<a href="about">About</a>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
About
<b class="caret"></b>
</a>
<ul class="dropdown-menu">
<li>
<a href="about"><i class="icon-edit"></i> About</a>
</li>
<li>
<a href="api"><i class="icon-align-center"></i> API</a>
</li>
</ul>
</li>
</ul>
<form class="pull-right navbar-search" action="search">