first commit

This commit is contained in:
douboer
2025-09-17 16:08:16 +08:00
parent 9395faa6b2
commit 3ff47c11d5
1318 changed files with 117477 additions and 0 deletions

View File

@@ -0,0 +1,43 @@
#!/usr/bin/perl -w
#############################################################################
# This example is a bit outdated, please use the new bin/graph-easy script -
# which is after "make install" available on any command line in your system.
# Convert an input file containing a Graph::Easy description to
# ASCII art.
# Example usage:
# examples/as_ascii t/in/2nodes.txt
# echo "[ A ] -> [ B ]" | examples/as_ascii
BEGIN { $|++; }
use lib 'lib';
use Graph::Easy::Parser;
my $file = shift;
my $id = shift || '';
my $debug = shift;
my $parser = Graph::Easy::Parser->new( debug => $debug );
if (!defined $file)
{
$file = \*STDIN;
binmode STDIN, ':utf8' or die ("binmode STDIN, ':utf8' failed: $!");
}
binmode STDERR, ':utf8' or die ("binmode STDERR, ':utf8' failed: $!");
my $graph = $parser->from_file( $file );
die ($parser->error()) unless defined $graph;
$graph->id($id);
$graph->timeout(360);
$graph->layout();
warn($graph->error()) if $graph->error();
binmode STDOUT, ':utf8' or die ("binmode STDOUT, ':utf8' failed: $!");
print $graph->as_ascii();

View File

@@ -0,0 +1,43 @@
#!/usr/bin/perl -w
#############################################################################
# This example is a bit outdated, please use the new bin/graph-easy script -
# which is after "make install" available on any command line in your system.
# Convert an input file containing a Graph::Easy description to
# ASCII art using "box drawing" Unicode characters.
# Example usage:
# examples/as_boxart t/in/2nodes.txt
# echo "[ A ] -> [ B ]" | examples/as_boxart
BEGIN { $|++; }
use lib 'lib';
use Graph::Easy::Parser;
my $file = shift;
my $id = shift || '';
my $debug = shift;
my $parser = Graph::Easy::Parser->new( debug => $debug );
if (!defined $file)
{
$file = \*STDIN;
binmode STDIN, ':utf8' or die ("binmode STDIN, ':utf8' failed: $!");
}
my $graph = $parser->from_file( $file );
die ($parser->error()) unless defined $graph;
$graph->id($id);
$graph->timeout(360);
$graph->layout();
warn($graph->error()) if $graph->error();
binmode STDOUT, ':utf8' or die ("binmode STDOUT, ':utf8' failed: $!");
print $graph->as_boxart();

View File

@@ -0,0 +1,44 @@
#!/usr/bin/perl -w
#############################################################################
# This example is a bit outdated, please use the new bin/graph-easy script -
# which is after "make install" available on any command line in your system.
# Convert an input file containing a Graph::Easy description to
# ASCII art using "box drawing" Unicode characters.
# Example usage:
# examples/as_boxart t/in/2nodes.txt
# echo "[ A ] -> [ B ]" | examples/as_boxart
BEGIN { $|++; }
use lib 'lib';
use Graph::Easy::Parser;
my $file = shift;
my $id = shift || '';
my $debug = shift;
my $parser = Graph::Easy::Parser->new( debug => $debug );
if (!defined $file)
{
$file = \*STDIN;
binmode STDIN, ':utf8' or die ("binmode STDIN, ':utf8' failed: $!");
}
my $graph = $parser->from_file( $file );
die ($parser->error()) unless defined $graph;
$graph->id($id);
$graph->timeout(360);
$graph->layout();
warn($graph->error()) if $graph->error();
binmode STDOUT, ':utf8' or die ("binmode STDOUT, ':utf8' failed: $!");
#print $graph->as_boxart();
print $graph->as_boxart_html_file();

View File

@@ -0,0 +1,35 @@
#!/usr/bin/perl -w
#############################################################################
# This example is a bit outdated, please use the new bin/graph-easy script -
# which is after "make install" available on any command line in your system.
# Convert an input file containing a Graph::Easy description to
# graphviz output that can be feed to dot etc.
# Example usage:
# examples/as_graphviz t/in/2nodes.txt | dot -Tpng >test.png
# echo "[ A ] -> [ B ]" | examples/as_graphviz | dot -Tpng >test.png
BEGIN { $|++; }
use strict;
use lib 'lib';
use Graph::Easy::Parser;
my $file = shift;
my $parser = Graph::Easy::Parser->new( debug => 0 );
if (!defined $file)
{
$file = \*STDIN;
binmode STDIN, ':utf8' or die ("binmode STDIN, ':utf8' failed: $!");
}
binmode STDERR, ':utf8' or die ("binmode STDERR, ':utf8' failed: $!");
my $graph = $parser->from_file( $file );
die ($parser->error()) unless defined $graph;
binmode STDOUT, ':utf8' or die ("binmode STDOUT, ':utf8' failed: $!");
print $graph->as_graphviz();

View File

@@ -0,0 +1,43 @@
#!/usr/bin/perl -w
#############################################################################
# This example is a bit outdated, please use the new bin/graph-easy script -
# which is after "make install" available on any command line in your system.
# Convert an input file containing a Graph::Easy description to
# an HTML page.
# Example usage:
# examples/as_html t/in/2nodes.txt >test.html
# echo "[ A ] -> [ B ]" | examples/as_ascii
BEGIN { $|++; }
use strict;
use lib 'lib';
use Graph::Easy::Parser;
my $file = shift;
my $id = shift || '';
my $debug = shift || 0;
my $parser = Graph::Easy::Parser->new( debug => $debug );
if (!defined $file)
{
$file = \*STDIN;
binmode STDIN, ':utf8' or die ("binmode STDIN, ':utf8' failed: $!");
}
binmode STDERR, ':utf8' or die ("binmode STDERR, ':utf8' failed: $!");
my $graph = $parser->from_file( $file );
die ($parser->error()) unless defined $graph;
$graph->id($id);
$graph->timeout(360);
$graph->layout();
warn ($graph->error()) if $graph->error();
binmode STDOUT, ':utf8' or die ("binmode STDOUT, ':utf8' failed: $!");
print $graph->as_html_page();

View File

@@ -0,0 +1,40 @@
#!/usr/bin/perl -w
#############################################################################
# This example is a bit outdated, please use the new bin/graph-easy script -
# which is after "make install" available on any command line in your system.
# Convert an input file containing a Graph::Easy description to
# standalone SVG file
# Example usage:
# examples/as_svg t/in/2nodes.txt >test.svg
# echo "[ A ] -> [ B ]" | examples/as_svg
BEGIN { $|++; }
use strict;
use lib 'lib';
use Graph::Easy::Parser;
my $file = shift;
my $debug = shift;
my $parser = Graph::Easy::Parser->new( debug => $debug );
if (!defined $file)
{
$file = \*STDIN;
binmode STDIN, ':utf8' or die ("binmode STDIN, ':utf8' failed: $!");
}
binmode STDERR, ':utf8' or die ("binmode STDERR, ':utf8' failed: $!");
my $graph = $parser->from_file( $file );
die ($parser->error()) unless defined $graph;
$graph->timeout(360);
$graph->layout();
warn ($graph->error()) if $graph->error();
binmode STDOUT, ':utf8' or die ("binmode STDOUT, ':utf8' failed: $!");
print $graph->as_svg_file();

View File

@@ -0,0 +1,39 @@
#!/usr/bin/perl -w
#############################################################################
# This example is a bit outdated, please use the new bin/graph-easy script -
# which is after "make install" available on any command line in your system.
# Convert an input file containing a Graph::Easy object, then dump
# it again as textual description.
# Example usage:
# examples/as_txt t/in/2nodes.txt
# echo "[ A ] -> [ B ]" | examples/as_txt
BEGIN { $|++; }
use lib 'lib';
use Graph::Easy::Parser;
my $file = shift;
my $id = shift || '';
my $debug = shift;
my $parser = Graph::Easy::Parser->new( debug => $debug );
if (!defined $file)
{
$file = \*STDIN;
binmode STDIN, ':utf8' or die ("binmode STDIN, ':utf8' failed: $!");
}
my $graph = $parser->from_file( $file );
die ($parser->error()) unless defined $graph;
$graph->id($id);
warn($graph->error()) if $graph->error();
binmode STDOUT, ':utf8' or die ("binmode STDOUT, ':utf8' failed: $!");
print $graph->as_txt();

View File

@@ -0,0 +1,28 @@
#!/usr/bin/perl -w
#############################################################################
# This example is a bit outdated, please use the new bin/grapheasy script -
# which is after "make install" available in your system as simple as
# "grapheasy" on any command line prompt.
#############################################################################
# This script uses examples/common.pl to generate some example graphs and
# displays them in ASCII.
use strict;
use warnings;
BEGIN { chdir 'examples' if -d 'examples'; }
require "common.pl";
sub out
{
my ($graph,$method) = @_;
$method = 'as_' . $method;
print $graph->$method(), "\n";
}
gen_graphs ();

View File

@@ -0,0 +1,179 @@
h1
{
border: 1px solid black;
padding: 0.2em;
background: #fff0f0;
margin-bottom: 0;
margin-top: 0;
padding-left: 0.5em;
}
h2
{
border: 1px solid gray;
border-bottom: none;
padding: 0.2em;
padding-left: 0.5em;
background: #e0e0f0;
margin-top: 0.8em;
margin-bottom: 0;
}
div.h3
{
border-bottom: 1px solid gray;
padding: 0.2em;
padding-left: 0.1em;
margin-top: 0;
margin-bottom: 0;
font-weight: bold;
font-size: 1.2em;
}
h2.green { background: #e0f0e0; }
h2.coral { background: #e0f0f0; }
h2.purple { background: #f0e0f0; }
h2.orange { background: #fff0d0; }
h2.brown { background: #e0b090; }
h2.lime { background: #e0f090; }
h2.honey { background: #f0f0a0; }
h2.mint { background: #c0ffe0; }
div.footer
{
background: #f0f0f0;
border: 1px solid gray;
padding: 0.6em;
padding-left: 1.6em;
font-size: small;
margin-top: 1em;
margin-bottom: 1em;
font-size: 0.8em;
}
p.hr
{
padding-top: 0.3em;
border: none;
border-top: 1px solid gray;
}
div.right
{
margin-left: 8.2em;
}
div.text
{
border: 1px solid gray;
padding: 0.5em;
padding-left: 1.5em;
background: #e8e8e8;
font-size: 0.9em;
}
.clear { clear: both; }
a.top
{
font-size: 0.8em;
float: right;
position: relative;
top: -2.5em;
right: 0.5em;
color: black;
font-weight: bold;
text-decoration: none;
padding: 0.2em;
}
a.top:hover
{
color: white;
background: black;
padding: 0.2em;
}
.menubck, .menuext, .menucur, .menuadd, .menuind, .menuinc, .menucin
{
display: block;
border: 1px solid gray;
padding: 0.1em;
padding-left: 0.5em;
margin: 0;
margin-bottom: 0.4em;
min-width: 7em;
font-size: 0.75em;
text-decoration: none;
background: #e0e0ff;
color: black;
}
.menuind, .menuinc, .menucin
{
min-width: 6em;
margin-left: 1em;
background: #e0e0ff;
}
.menu
{
background: white;
padding: 0em;
margin: 0;
border: none;
width: 7em;
margin-right: 0.2em;
position: fixed;
}
.menucur, .menucin { border-color: #404040; }
.menucin { background: #a0a0ff; }
.menucur { background: #a0a0ff; }
.menuadd { background: #f0a0a0; }
.menuind { background: #d0d0ff; }
.menubck { background: #f0b0b0; }
:hover
{
color: #ffffff;
background: #000000;
}
.menubck:hover, .menuadd:hover { background: #a03030; }
.menucur:hover { background: #000080; }
.menuind:hover, .menucin:hover { background: #3030a0; }
img.i
{
border: none;
}
img
{
border: 1px solid gray;
margin-top: 0.7em;
margin-bottom: 0.7em;
}
p, li
{
max-width: 50em;
}
p {
padding-bottom: 0;
margin-bottom: 0.4em;
margin-top: 0.4em;
}
ul
{
list-style: square;
}
li
{
font-size: 0.9em;
}
tr.odd td
{
background: #ffdead;
}
code
{
background: #ffffff;
color: black;
padding: 2px;
}
pre
{
background: #d0d0d0;
color: black;
padding: 0.8em;
margin-left: 1em;
margin-bottom: 2.5em;
border: 1px solid black;
max-width: 40em;
}

View File

@@ -0,0 +1,74 @@
#!/usr/bin/perl -w
#############################################################################
# This script is used by both examples/ascii.pl and examples/html.pl to
# generate some sample graphs and then outputting them in the desired format.
use strict;
use warnings;
BEGIN
{
use lib '../lib';
}
use Graph::Easy;
sub gen_graphs
{
my $graph = shift || Graph::Easy->new();
my $method = shift || 'ascii';
###########################################################################
my $node = $graph->add_node( 'Bonn' );
my $node2 = $graph->add_node( 'Berlin' );
$graph->add_edge( $node, $node2 );
out ($graph, $method);
###########################################################################
$graph->{debug} = 0;
my $node3 = $graph->add_node( 'Frankfurt' );
$node3->set_attribute('border-style', 'dotted');
my $edge3 = Graph::Easy::Edge->new( style => 'double' );
$graph->add_edge( $node2, $node3, $edge3 );
out ($graph, $method);
###########################################################################
$graph->add_edge( $node3, 'Dresden' );
out ($graph, $method);
###########################################################################
$graph->add_edge( $node2, 'Potsdam' );
out ($graph, $method);
###########################################################################
my $node6 = $graph->add_node( 'Cottbus',);
$node6->set_attribute('border', '1px red dashed');
my $edge5 = $graph->add_edge( 'Potsdam', $node6 );
out ($graph, $method);
###########################################################################
$graph->add_edge( $node6, $node3 );
out ($graph, $method);
$graph->add_edge( $node6, $node3 );
out ($graph, $method);
}
1;

View File

@@ -0,0 +1,22 @@
graph {
border: 1px solid black;
fill: oldlace;
background: goldenrod;
label: My sample graph;
}
edge { label-color: green; color: blue; }
[ One ] { fill: seagreen; color: white; } -- label --> [ Two ] { shape: triangle; }
[ One ] => { arrow-style: closed; } [ Three ]
[ Five ] { fill: maroon; color: yellow; } <=> [ Three ]
[ One ] .. Test\n label ..> [ Four ]
[ Three ] { border-style: dashed; }
.. Test\n label ..> { arrow-style: closed; } [ Six ] { label: Sixty\n Six\nand\nsix; }
[ Five ] - Test label - > { label-color: darkslategrey; color: red; } [ Seven ]
[ Seven ] -- [ Eight ]
[ Five ] --> [ Eight ]
[ Five ] --> [ Seven ]
[ Two ] -> [ Four ]
[ Three ] <-- Test label --> { arrow-style: closed; } [ Six ]
[ Eight ] .. [ None ] { shape: none; fill: red; color: brown; }

View File

@@ -0,0 +1,59 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>&lt;graph&gt;-Plugin for Mediawiki - Syntax</title>
<meta name="MSSmartTagsPreventParsing" content="TRUE">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="imagetoolbar" content="no">
<link rel="stylesheet" type="text/css" href="base.css">
<style type="text/css">
<!--
.graph { margin-left: 2em; }
pre { margin-right: 1.5em; }
h3 { border-bottom: 1px solid #404040; padding-bottom: 0.3em; }
a.top { top: -3.5em; }
-->
</style>
</head>
<body bgcolor=white text=black>
<a name="top"></a>
<div class="menu">
<a class="menubck" href="index.html" title="Back to the main page">Main</a>
</div>
<div class="right">
<h1>&lt;graph&gt;-Plugin for Mediawiki</h1>
<h2>Table of Contents:</h2>
<div class="text">
##TOC##
<p>
To see the input text for each graph, follow the <font color="red">Source</font> link in each section.
</p>
</div>
<h2>Fun with Graphs</h2>
<div class="text">
##HTML##
</div>
<div class="footer">
<p>
This page was automatically created at <strong><small>##time##</small></strong> by <code>examples/syntax.pl</code> running
<a href="http://search.cpan.org/~tels/Graph-Simple/" title="Get it from search.cpan.org">Graph::Easy</a> v##version##.
Contact <a href="/mail.html">Tels</a> for help.
</p>
</div>
</div> <!-- right cell ends here -->
</body></html>

View File

@@ -0,0 +1,6 @@
[ Bonn ] -> [ Berlin ]
[ Berlin ] -> [ Frankfurt ]
[ Frankfurt ] -> [ Dresden ]
[ Berlin ] -> [ Potsdam ]
[ Potsdam ] -> [ Cottbus ] { border-color: red; }
[ Cottbus ] -> [ Frankfurt ]

View File

@@ -0,0 +1,113 @@
#!/usr/bin/perl -w
#############################################################################
# This example is a bit outdated, please use the new bin/grapheasy script -
# which is after "make install" available in your system as simple as
# "grapheasy" on any command line prompt.
#############################################################################
# This script uses examples/common.pl to generate some example graphs and
# prints them as HTML page. Use it like:
# ewxamples/html.pl >test.html
# and then open test.html in your favourite browser.
use strict;
use warnings;
BEGIN { chdir 'examples' if -d 'examples'; }
require "common.pl";
my $graph = Graph::Easy->new();
my @toc = ();
my $html = $graph->html_page_header();
$html .= <<HTML
<style type="text/css">
h1 { border-bottom: 1px solid black; padding-bottom: 0.2em; }
h2 { border-bottom: 1px solid grey; padding-bottom: 0.2em; margin-bottom: 0em; }
div { margin-left: 2em; }
.graph { margin-left: 2em; }
</style>
<h1>Graph-Simple Test page</h1>
<p>
This page was automatically created at <small>##time##</small> by <code>examples/html.pl</code> running
<a href="http://search.cpan.org/~tels/Graph-Simple/" title="Get it from search.cpan.org">Graph::Easy</a> v##version##.
</p>
<p>
On each of the following testcases you will see a text representation of the graph on the left side,
and on the right side the automatically generated HTML+CSS code.
</p>
<p>
Notes:
</p>
<ul>
<li>The text representation does not yet carry node attributes, like colors or border style.
<li>The HTML does not yet have "pretty" edges. This will be fixed later.
<li>The limitations in <a href="http://search.cpan.org/~tels/Graph-Simple/lib/Graph/Simple.pm#LIMITATIONS">Graph::Easy</a> apply.
</ul>
<h2>Testcases:</h2>
##TOC##
HTML
;
# generate the parts and push their names into @toc
gen_graphs($graph, 'html');
$html .= $graph->html_page_footer();
my $toc = '<ul>';
for my $t (@toc)
{
my $n = $t; $n =~ s/\s/_/;
$toc .= " <li><a href=\"#$n\">" . $t . "</a>\n";
}
$toc .= "</ul>\n";
# insert the TOC
$html =~ s/##TOC##/ $toc /;
$html =~ s/##time##/ scalar localtime() /e;
$html =~ s/##version##/$Graph::Easy::VERSION/e;
print $html;
# all done;
1;
#############################################################################
sub out
{
my ($graph,$method) = @_;
$method = 'as_' . $method;
my $t = $graph->nodes() . ' Nodes, ' . $graph->edges . ' Edges';
my $n = $t; $n =~ s/\s/_/;
$html .= "<a name=\"$n\"><h2>$t</h2></a>\n" .
"<div style='float: left; min-widht: 30%'>\n" .
"<h3>As Text</h3>\n" .
"<pre>" . $graph->as_txt() . "</pre></div>" .
"<div style='float: left;'>\n" .
"<h3>As HTML:</h3>\n" .
$graph->$method() . "</div>\n" .
"<div style='clear: both;'>&nbsp;</div>\n\n";
push @toc, $t;
}

View File

@@ -0,0 +1,39 @@
#!/usr/bin/perl -w
BEGIN { $|++; }
use strict;
use lib 'lib';
use Graph::Easy::Parser;
print "# Graph::Easy v$Graph::Easy::VERSION\n";
my $file = shift;
$file = \*STDIN unless defined $file;
my $id = shift || '';
my $debug = shift || 0;
my $parser = Graph::Easy::Parser->new( debug => $debug );
my $graph = $parser->from_file( $file );
print "# input: '$file'\n";
die ($parser->error()) unless defined $graph;
print "# Graph has ", scalar $graph->nodes(),
" nodes and ", scalar $graph->edges()," edges.\n";
$graph->id($id);
$graph->timeout(240);
$graph->layout();
warn ($graph->error()) if $graph->error();
print $graph->as_txt();
print $graph->as_ascii(), "\n";
print "<style type='text/css'>\n<!--\n",
$graph->css(), "--></style>\n", $graph->as_html();

View File

@@ -0,0 +1,211 @@
#!/usr/bin/perl -w
#############################################################################
# This example is a bit outdated, please use the new bin/grapheasy script -
# which is after "make install" available in your system as simple as
# "grapheasy" on any command line prompt.
#############################################################################
# This script tries to generate graphs from all the files in t/syntax/
# and outputs the result as an HTML page.
# Use it like:
# examples/syntax.pl >test.html
# and then open test.html in your favourite browser.
BEGIN
{
chdir 'examples' if -d 'examples';
use lib '../lib';
}
use strict;
use warnings;
use Graph::Easy::Parser;
my $parser = Graph::Easy::Parser->new( debug => 0);
my ($name, $template, $sep, @dirs) = @ARGV;
$name = 'Graph::Easy Test page' unless $name;
$template = 'syntax.tpl' unless $template;
my @toc = ();
open FILE, $template or die ("Cannot read 'syntax.tpl': $!");
local $/ = undef;
my $html = <FILE>;
close FILE;
my $output = ''; my $ID = '0';
# generate the parts and push their names into @toc
gen_graphs($parser, @dirs);
my $toc = '<ul>';
for my $t (@toc)
{
$toc .= " <li><a href='#$t->[0]'>$t->[1]</a>\n";
}
$toc .= "</ul>\n";
# insert the TOC
$html =~ s/##TOC##/ $toc /;
$html =~ s/##NAME##/ $name /;
$html =~ s/##HTML##/ $output /;
$html =~ s/##time##/ scalar localtime() /eg;
$html =~ s/##version##/$Graph::Easy::VERSION/eg;
print $html;
# all done;
1;
#############################################################################
sub gen_graphs
{
# for all files in a dir, generate a graph from it
my $parser = shift;
@dirs = qw/syntax stress/ unless @dirs;
foreach my $dir (@dirs)
{
_for_all_files($parser, $dir);
}
}
sub _for_all_files
{
my ($parser, $dir) = @_;
opendir DIR, "../t/$dir" or die ("Cannot read dir '../t/$dir': $!");
my @files = readdir DIR;
closedir DIR;
foreach my $file (sort @files)
{
my $f = "../t/$dir/" . $file;
next unless -f $f; # not a file?
print STDERR "# at file $f\n";
open FILE, "$f" or die ("Cannot read '$f': $!");
local $/ = undef;
my $input = <FILE>;
close FILE;
my $graph = $parser->from_text( $input );
if (!defined $graph)
{
my $error = $parser->error();
$output .=
"<h2>$dir/$file</h2>" .
"<a class='top' href='#top' title='Go to the top'>Top -^</a>\n".
"<div class='text'>\n".
"Error: Could not parse input from $file: <b style='color: red;'>$error</b>".
"<br>Input was:\n" .
"<pre>$input</pre>\n".
"</div>\n";
next;
}
$graph->timeout(100);
$graph->layout();
if ($graph->error())
{
my $error = $graph->error();
$output .=
"<h2>$dir/$file</h2>" .
"<a class='top' href='#top' title='Go to the top'>Top -^</a>\n".
"<div class='text'>\n".
"Error: $error</b>".
"<br>Input was:\n" .
"<pre>$input</pre>\n".
"</div>\n";
next;
}
$output .= out ($input, $graph, 'html', $dir, $file);
}
}
sub out
{
my ($txt,$graph,$method,$dir, $file) = @_;
$method = 'as_' . $method;
# set unique ID for CSS
$graph->id($ID++);
my $t = $graph->nodes() . ' Nodes, ' . $graph->edges . ' Edges';
my $n = $dir."_$file";
$dir = ucfirst($dir);
# get comment
$txt =~ /^\s*#\s*(.*)/;
my $comment = ucfirst($1 || '');
my $link;
$link = $1 if $txt =~ /\n#\s*(http.*)/;
my $name = $comment || $t;
push @toc, [ $n, $name ];
my $out =
"<style type='text/css'>\n" .
"<!--\n" .
$graph->css() .
"-->\n" .
"</style>\n";
if (!$sep)
{
$out .=
"<a name=\"$n\"></a><h2>$dir: $name</h2>\n" .
"<a class='top' href='#top' title='Go to the top'>Top -^</a>\n".
"<div class='text'>\n";
$out .= "<span style='color: red; font-weight: bold;'>Error: </span>" .
$graph->error() if $graph->error();
my $input =
"<div style='float: left;'>\n" .
" <h3>Input</h3>\n" .
" <pre>$txt</pre>\n</div>" .
"<div style='float: left;'>\n" .
" <h3>As Text</h3>\n" .
"<pre>" . $graph->as_txt() . "</pre>\n</div>";
$out .= $input .
"<div style='float: left;'>\n" .
"<h3>As HTML:</h3>\n" .
$graph->$method() . "\n</div>\n";
$out .= "<div class='clear'>&nbsp;</div></div>\n\n";
}
else
{
$out .=
"<a name=\"$n\"></a><h3>$name</h3>\n";
$out .= "<a class='top' href='#top' title='Go to the top'>Top -^</a>\n";
$out .= "<a class='top' href='$link' style='color: red;'>Source</a>\n" if $link;
$out .= "<span style='color: red; font-weight: bold;'>Error: </span> " .
$graph->error() if $graph->error();
$out .= $graph->$method() . "\n" .
"<div class='clear'></div>\n\n";
# write out the input/text
}
$out;
}

View File

@@ -0,0 +1,72 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>&lt;graph&gt;-Plugin for Mediawiki - Syntax</title>
<meta name="MSSmartTagsPreventParsing" content="TRUE">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="imagetoolbar" content="no">
<link rel="stylesheet" type="text/css" href="base.css">
<style type="text/css">
.graph { margin-left: 2em; }
pre { margin-right: 1.5em; }
</style>
</head>
<body bgcolor=white text=black>
<a name="top"></a>
<div class="menu">
<a class="menubck" href="index.html" title="Back to the main page">Main</a>
</div>
<div class="right">
<h1>&lt;graph&gt;-Plugin for Mediawiki</h1>
<h2>##NAME##</h2>
<div class="text">
<p>
This page was automatically created at <strong><small>##time##</small></strong> by <code>examples/syntax.pl</code> running
<a href="http://search.cpan.org/~tels/Graph-Simple/" title="Get it from search.cpan.org">Graph::Easy</a> v##version##.
</p>
<p>
On each of the following testcases you will see the original text
representation of the graph, a text representation created automatically
from the parsed input, as well the automatically generated HTML+CSS code.
</p>
<p>
<strong>Notes:</strong>
</p>
<ul>
<li>The limitations in
<a href="http://search.cpan.org/~tels/Graph-Simple/lib/Graph/Simple.pm#LIMITATIONS">Graph::Easy</a> apply.
</ul>
</div>
<h2>Table of Contents:</h2>
<div class="text">
##TOC##
</div>
##HTML##
<div class="footer">
<p>
This page was automatically created at <strong><small>##time##</small></strong> by <code>examples/syntax.pl</code> running
<a href="http://search.cpan.org/~tels/Graph-Simple/" title="Get it from search.cpan.org">Graph::Easy</a> v##version##.
Contact <a href="/mail.html">Tels</a> for help.
</p>
</div>
</div> <!-- right cell ends here -->
</body></html>

View File

@@ -0,0 +1,318 @@
#!/usr/bin/perl
use strict;
use Graph::Easy;
use LWP;
use HTML::TokeParser;
use utf8;
use Getopt::Long;
use Encode;
use Data::Dumper;
my $VERSION = 0.03;
# things that shouldn't be looked at
my %bad = map { $_ => 1 } qw/
Wikipedia Image Talk Help Template Portal Special User Category
Wikipedia Bild Diskussion Hilfe Vorlage Portal Spezial Benutzer Kategorie
Wikipédia Image Discuter Modèle Mod%C3%A9le Aide Utilisateur Catégorie Cat%C3%A9gorie
/;
# do not crawl these:
my $skip = qr/\((disambiguation|Begriffsklärung|Homonymie)\)/i;
# to figure out redirections
my $redir = qr/(Weitergeleitet von|Redirected from|Redirig. depuis).*?title="(.*?)"/i;
# the default settings are defined in get_options()
# option handling
my $help_requested = 0; $help_requested = 1 if @ARGV == 0;
my $opt = get_options();
# error?
$help_requested = 1 if !ref($opt);
# no error and --help was specified
$help_requested = 2 if ref($opt) && $opt->{help} ne '';
my $copyright = "wikicrawl v$VERSION (c) by Tels 2008. "
."Released under the GPL 2.0 or later.\n\n"
."After a very cool idea by 'integral' on forum.xkcd.com. Thanx! :)\n\n";
if (ref($opt) && $opt->{version} != 0)
{
print $copyright;
print "Running under Perl v$].\n\n";
exit 2;
}
if ($help_requested > 0)
{
print STDERR $copyright;
require Pod::Usage;
if ($help_requested > 1 && $Pod::Usage::VERSION < 1.35)
{
# The way old Pod::Usage executes "perldoc" might fail:
system('perldoc', $0);
exit 2;
}
Pod::Usage::pod2usage( { -exitval => 2, -verbose => $help_requested } );
}
my $verbose = $opt->{verbose};
output ($copyright);
my $graph = Graph::Easy->new();
# set some default attributes on the graph
$graph->set_attribute('node','shape',$opt->{nodeshape});
$graph->set_attribute('node','font-size','80%');
$graph->set_attribute('edge','arrowstyle','filled');
$graph->set_attribute('graph','label',"Wikipedia map for $opt->{root}");
$graph->set_attribute('graph','font-size', '200%');
$graph->set_attribute('graph','comment', "Created with wikicrawl.pl v$VERSION");
output ("Using the following settings:\n");
print Data::Dumper->Dump([$opt], ['opt']);
# don't crawl stuff twice
my %visitedLinks;
# re-use the UserAgent object
my $ua = LWP::UserAgent->new();
#$ua->agent("WikiCrawl/$VERSION - " . $ua->_agent . " - vGraph::Easy $Graph::Easy::VERSION");
# count how many we have done
my $nodes = 0;
# enable UTF-8 output
binmode STDERR, ':utf8';
binmode STDOUT, ':utf8';
# push the first node on the stack
my @todo = [$opt->{root},0];
# and work on it (this will take one off and then push more nodes on it)
while (@todo && crawl()) { };
my $file = "wikicrawl-$opt->{lang}.txt";
output ("Generating $file:\n");
open(my $DATA, ">", "$file") or die("Could not write to '$file': $!");
binmode ($DATA,':utf8');
print $DATA $graph->as_txt();
close $DATA;
output ("All done.\n");
my $png = $file; $png =~ s/.txt/.png/;
output ("Generating $png:\n");
`perl -Ilib bin/graph-easy --png --renderer=$opt->{renderer} $file`;
output ("All done.\n");
########################################################################################
# main crawl routine
sub crawl {
no warnings 'recursion';
# all done?
return if @todo == 0;
my ($name,$depth) = ($todo[0]->[0],$todo[0]->[1]);
shift @todo;
my $page = "http://$opt->{lang}.wikipedia.org/wiki/$name";
# limit depth
return if $depth + 1 > $opt->{maxdepth};
# already did as many nodes?
return if $opt->{maxnodes} > 0 && $nodes > $opt->{maxnodes};
# skip this page
return 1 if exists $visitedLinks{$page};
# crawl page
my $res = $ua->request(HTTP::Request->new(GET => $page));
return 1 unless $res->is_success();
# remove the " - Wikipedia" (en) or " Wikipedia" (de) from the title
my $title = decode('utf8',$res->title); # convert to UTF-8
$title =~ s/ [-] Wikip[ée]dia.*//;
return 1 if $title =~ $skip; # no disambiguation pages
# tels: not sure when/why these happen:
print STDERR "# $title ",$res->title()," $page\n" if $title eq '';
output ("Crawling node #$nodes '$title' at depth $depth\n"); $nodes++;
# set flag
$visitedLinks{$page} = undef;
my $content = $res->content;
# parse anchors
my $parser = HTML::TokeParser->new(\$content) or die("Could not parse page.");
# handle redirects:
$content = decode('utf-8', $content);
$content =~ $redir; my $old = $2;
if ($old)
{
output (" Redirected to '$title' from '$old'\n");
# find the node named "$old" (at the same time adding it if it didn't exist yet)
my $source = $graph->add_node($old);
# and mention the redirect in the label
$source->set_attribute('label', "$old\\n($title)");
# now force edges to come from that node
$title = $old;
}
# iterate over all links
for(my $i = 0; (my $token = $parser->get_tag("a")) && ($i < $opt->{maxspread} || $opt->{maxspread} == 0);)
{
my $url = $token->[1]{href};
my $alt = $token->[1]{title};
next unless defined $url;
# we do not crawl these:
next if $url !~ m/^\/wiki\//; # no pages outside of wikipedia
next if $alt =~ $skip; # no disambiguation pages
next if $alt =~ m/\[/; # no brackets
my @chunks = split ":", substr(decode('utf-8',$url), 6); # extract special pages, if any
next if exists $bad{$chunks[0]}; # no bad pages
$i++;
if ($title ne $alt)
{
output (" Adding link from '$title' to '$alt'\n", 1);
my ($from,$to,$edge) = $graph->add_edge_once($title,$alt);
if (defined $to)
{
my $old_depth = $to->raw_attribute('rank');
if (!$old_depth)
{
my $color = sprintf("%i", (360 / $opt->{maxdepth}) * ($depth));
$to->set_attribute('fill', 'hsl(' .$color.',1,0.7)');
# store rank
$to->set_attribute('rank', $depth+1);
}
}
}
my $u = $url; $u =~ s/^\/wiki\///;
push @todo, [$u,$depth+1];
}
# continue
return 1;
}
sub get_options
{
my $opt = {};
$opt->{help} = '';
$opt->{version} = 0;
# max depth to crawl
$opt->{maxdepth} = 4;
# max number of links per node
$opt->{maxspread} = 5;
# stop after so many nodes, -1 to disable
$opt->{maxnodes} = -1;
# language
$opt->{lang} = 'en';
# root node
$opt->{root} = 'Xkcd';
$opt->{renderer} = 'neato';
$opt->{nodeshape} = 'rect';
my @o = (
"language=s" => \$opt->{lang},
"root=s" => \$opt->{root},
"maxdepth=i" => \$opt->{maxdepth},
"maxspread=i" => \$opt->{maxspread},
"maxnodes=i" => \$opt->{maxnodes},
"version" => \$opt->{version},
"help|?" => \$opt->{help},
"verbose" => \$opt->{verbose},
"nodeshape" => \$opt->{nodeshape},
);
return unless Getopt::Long::GetOptions (@o);
$opt;
}
sub output
{
my ($txt, $level) = @_;
$level |= 0;
print STDERR $txt if $opt->{verbose} || $level == 0;
}
=pod
=head1 NAME
wikicrawl - crawl Wikipedia to generate graph from the found article links
=head1 SYNOPSIS
Crawl wikipedia and create a L<Graph::Easy> text describing the inter-article links
that were found during the crawl.
At least one argument must be given to start:
perl examples/wikicrawl.pl --lang=fr
=head1 ARGUMENTS
Here are the options:
=over 12
=item --help
Print the full documentation, not just this short overview.
=item --version
Write version info and exit.
=item --language
Select the language of Wikipedia that we should crawl. Currently supported
are 'de', 'en' and 'fr'. Default is 'en'.
=item --root
Set the root node where the crawl should start. Default is of course 'Xkcd'.
=item --maxdepth
The maximum depth the crawl should go. Please select small values under 10. Default is 4.
=item --maxspread
The maximum number of links we follow per article. Please select small values under 10. Default is 5.
=item --maxnodes
The maximum number of nodes we crawl. Set to -1 (default) to disable.
=back
=head1 SEE ALSO
L<http://forums.xkcd.com/viewtopic.php?f=2&t=21300&p=672184> and
L<Graph::Easy>.
=head1 LICENSE
This library is free software; you can redistribute it and/or modify
it under the terms of the GPL.
See the LICENSE file of Graph::Easy for a copy of the GPL.
X<license>
=head1 AUTHOR
Copyright (C) 2008 by integral L<forum.xkcd.com>
Copyright (C) 2008 by Tels L<http://bloodgate.com>
=cut