1package PerlPoint::Converters; 2 3$VERSION = "1.0205"; 4 5use File::Copy; 6use Cwd; 7use Carp; 8use Exporter; 9@ISA = qw(Exporter); 10 11@EXPORT_OK = qw( 12 replace_keywords 13 update_file 14 copy_file 15 return_abs_path 16 relative_path 17 is_abs_path 18); 19use strict; 20 21=head1 NAME 22 23PerlPoint::Converters - README and common functions for PerlPoint converters 24 25=head1 README 26 27Covered topics: 28 29=over 4 30 31=item * 32 33Introduction 34 35=item * 36 37About PerlPoint-Converters 38 39=item * 40 41Prerequisits 42 43=item * 44 45What's new 46 47=item * 48 49Installation 50 51=item * 52 53Documentation 54 55=item * 56 57Test Cases 58 59=item * 60 61Bug Reports and Support 62 63=item * 64 65Credits 66 67=item * 68 69Licence 70 71=back 72 73=head2 Introduction 74 75PerlPoint is a simple text format which allows easy typing of text 76with headlines, bullet lists, normal text paragraphs, indented 77paragraphs for code examples etc., from which slides for presentations 78can be generated by a script without the need of proprietary software. 79Since there is a large variety of platforms which provide web browsers, 80HTML is a good choice for the output format. In principle, however, it 81is possible to generate each output format whose specification is 82known. At the moment there exist converters for HTML, LaTeX (alpha software) 83and SDF. The latter both may be used to generate printable output or to 84provide the basis for further processing. 85 86 87=head2 About PerlPoint-Converters 88 89This package provides two programs: 90 91 pp2html 92 pp2latex (still alpha software) 93 94They convert an ASCII file written in the `PerlPoint' language to a set 95of HTML files or to Latex Files respectively. The `PerlPoint' language 96was initially invented by Tom Christiansen as a simple means for 97preparing slides. The idea was to just write down your headings and 98bullet items and then use a simple perl script to create the slides: 99 100 =Header of first slide 101 102 * Use your favourite editor 103 104 * Start headings with a `=' 105 106 * Bullets items start with an asterisk `*' 107 108The syntax of the original version was similar to POD and the layout 109of the slides was hard coded in Tom's pp2html script. The new syntax 110provides more felxibility and can be parsed with the PerlPoint::Parser 111from Jochen Stenzel's PerlPoint-Package. 112 113The following list persents some of the features of pp2html and pp2latex: 114 115 - HTML template files for header, footer and navigation bar 116 - Support of Frame Sets 117 - Support of the TreeControl Applet in tabel of contents 118 - Headers with different levels with or wihout numbering 119 (1, 1.1, 1.2, 2, ...) 120 - Hyperlinks to internal and external pages 121 - Automatic generation of table of contents and navigation links 122 - Automatic generation of index 123 - Bullet-Lists with standard <LI> bullets or with bullets from 124 a gif/jpeg file 125 - Numbered lists and definition lists 126 - Simple tables 127 - Simple text formatting possible 128 129For more information about the PerlPoint syntax and history please 130refer to the documentation in the PerlPoint-Package from Jochen Stenzel 131(perldoc PerlPoint::Parser) and to the provided documentation in the 132./doc/PPDOC subdirectory (after a successful "make" in ./doc :-) 133 134 135=head2 Prerequisits 136 137This version needs Perl5.005. 138 139The pp2html program uses the following packages which are available on CPAN 140or come with your Perl distribution: 141 142 Pod::Text 143 Getopt::Long 144 Getopt::ArgvFile 145 PerlPoint::Parser 146 PerlPoint::Backend 147 PerlPoint::Constants 148 PerlPoint::Tags::Basic; 149 PerlPoint::Tags::HTML; (part of PerlPoint-Converters) 150 PerlPoint::Tags::LaTeX; (part of PerlPoint-Converters) 151 152The TreeApplet classes are contained in the pp2html_stypes subdirectory of this 153distribution. For more information about the TreeApplet classes refer to 154http://www.naturallyj.com. 155This distribution contains an older version which was freely available. 156 157 158=head2 What's new in this version 159 160This is version 1.00. 161You will need PerlPoint-Packet version 0.36 for this release. 162 163Please refer to file "Changes". 164 165=over 4 166 167=item NOTE: 168 169Documentation is not yet perfect, but hopefully better than before. 170Please try a "make" in ./doc and look at the documents which 171should have been created in ./doc/PPDOC 172 173=back 174 175=head2 Installation 176 177Just get the PerlPoint-Converters-<release>.tar.gz file and unpack it in a temp directory: 178 179 % tar zxvf PerlPoint-Converters-<release>.tar.gz 180 % cd PerlPoint-Converters-<release> 181 % perl Makefile.PL 182 % make 183 % make test 184 % make install 185 186 % cd ./doc 187 % make 188 189The main program is `pp2html'. Try `pp2html --help | less' to get more 190information. 191 192=head2 Documentation 193 194C<pp2hml> and C<pp2latex> have a --help option which displays 195Usage information and some documentation about the PerlPoint 196Language. For a more detailed description please refer to the 197POD documentation of the following Modules: 198 199 PerlPoint::Parser 200 PerlPoint::Anchors 201 PerlPoint::Backend 202 PerlPoint::Constants 203 PerlPoint::Tags 204 PerlPoint::Tags::Basic 205 PerlPoint::Tags::CPPP 206 PerlPoint::Tags::HTML 207 PerlPoint::Tags::LaTeX 208 PerlPoint::Tags::SDF 209 210Have also a look into the ./doc directory of your PerlPoint::Converters 211installation directory. There is a Makefile which produces the 212following PerlPoint documents: 213 214=over 4 215 216=item * 217 218Getting_Started 219 220=item * 221 222FAQ-pp2html 223 224=item * 225 226FAQ-parser 227 228=item * 229 230Writing-Converters 231 232=back 233 234 235=head2 Test Cases 236 237The examples test cases from the previous releases (ex_std_norm, 238ex_std_tree, ex_frm_norm and ex_frm_tree) have now been replaced 239with the documentation in the ./doc subdirectory. 240 241 242=head2 Bug Reports and Support 243 244Please send bug reports and requests to <lorenz.domke@gmx.de> 245There is also a mailing list for PerlPoint: 246 247 perlpoint@perl.org 248 249To join the mailing list, send a message to C<perlpoint-subscribe@perl.org> 250 251 252 253 254=head2 Credits 255 256Thanks to Tom Christiansen for the idea and first implementation 257of PerlPoint! And special thanks for his permission to use this 258name for our new implementation. 259 260Thanks to Jochen Stenzel who tested the first versions of pp2html 261and supplied the powerful PerlPoint-Package which is the base of 262this new implementation of pp2html. 263 264Thanks to Stephen Riehm who shared his ideas of extensions for 265the original software with us. The final language was basically 266designed by a team of Jochen, him and me. 267 268Thanks to Alex Sigel and Norbert Gruener who became our first 269testers outside the team and helped us by their usage reports. 270Special thanks to Alex for propagating the toolkit and his help 271to publish the software! 272 273 274=head2 Licence 275 276This module is free software, you can redistribute it and/or modify it 277under the terms of the Artistic License distributed with Perl version 2785.003 or (at your option) any later version. Please refer to the 279Artistic License that came with your Perl distribution for more 280details. 281 282The Artistic License should have been included in your distribution of 283Perl. It resides in the file named "Artistic" at the top-level of the 284Perl source tree (where Perl was downloaded/unpacked - ask your 285system administrator if you dont know where this is). Alternatively, 286the current version of the Artistic License distributed with Perl can 287be viewed on-line on the World-Wide Web (WWW) from the following URL: 288http://www.perl.com/perl/misc/Artistic.html 289 290DISCLAIMER 291 292This software is distributed in the hope that it will be useful, but 293is provided "AS IS" WITHOUT WARRANTY OF ANY KIND, either expressed or 294implied, INCLUDING, without limitation, the implied warranties of 295MERCHANTABILITY and FITNESS FOR A PARTICULAR PURPOSE. 296 297The ENTIRE RISK as to the quality and performance of the software 298IS WITH YOU (the holder of the software). Should the software prove 299defective, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR 300CORRECTION. 301 302IN NO EVENT WILL ANY COPYRIGHT HOLDER OR ANY OTHER PARTY WHO MAY CREATE, 303MODIFY, OR DISTRIBUTE THE SOFTWARE BE LIABLE OR RESPONSIBLE TO YOU OR TO 304ANY OTHER ENTITY FOR ANY KIND OF DAMAGES (no matter how awful - not even 305if they arise from known or unknown flaws in the software). 306 307Please refer to the Artistic License that came with your Perl 308distribution for more details. 309 310 311=head1 SYNOPSIS 312 313 use PerlPoint::Converters qw( 314 replace_keywords 315 update_file 316 copy_file 317 ); 318 319 copy_file($from, $to); 320 321 update_file($from, $to); 322 323 $line = replace_keywords($line, $KEY_HASH_REF); 324 325=head1 DESCRIPTION 326 327This module contains some common functions which are 328useful for most PerlPoint converters. 329 330=head1 SUBROUTINES 331 332=cut 333 334sub replace_keywords { #{{{----------------------------------------- 335 336=head2 replace_keywords($line, $KEY_HASH_REF); 337 338Replace all occurences of certain keywords in $line with the 339values specified in the referenced hash. 340The keys in the hash must be lower case keywords. 341 342Example: 343 344 %OPT = ( 345 title => "PerlPoint Examples", 346 bot_left_txt => "Copyright A. User", 347 ); 348 349 open(TPL, "a_template_file"); 350 while(<TPL>){ 351 print replace_keywords($_, \%OPT); 352 } 353 354This will replace "TITLE" with "PerlPoint Examples" and "BOT_LEFT_TXT" 355with "Copyright A. User". 356 357The supported keywords are: 358 359 TXT_CONTENTS 360 TXT_INDEX 361 PAGE_CNT 362 TITLE 363 BASE_LEFT_TXT 364 BASE_RIGHT_TXT 365 BASE_MIDDLE_TXT 366 BOT_LEFT_TXT 367 BOT_RIGHT_TXT 368 BOT_MIDDLE_TXT 369 TOP_LEFT_TXT 370 TOP_RIGHT_TXT 371 TOP_MIDDLE_TXT 372 373 BGCOLOR 374 FGCOLOR 375 BOT_BGCOLOR 376 TOP_BGCOLOR 377 IDX_BGCOLOR 378 TOC_BGCOLOR 379 BOT_FGCOLOR 380 TOP_FGCOLOR 381 IDX_FGCOLOR 382 TOC_FGCOLOR 383 LINKCOLOR 384 TOP_LINKCOLOR 385 BOT_LINKCOLOR 386 TOC_LINKCOLOR 387 IDX_LINKCOLOR 388 ALINKCOLOR 389 TOP_ALINKCOLOR 390 BOT_ALINKCOLOR 391 TOC_ALINKCOLOR 392 IDX_ALINKCOLOR 393 VLINKCOLOR 394 TOP_VLINKCOLOR 395 BOT_VLINKCOLOR 396 TOC_VLINKCOLOR 397 IDX_VLINKCOLOR 398 399 LABEL_NEXT 400 LABEL_PREV 401 LABEL_INDEX 402 LABEL_CONTENTS 403 404 SLIDE_PREFIX 405 SLIDE_SUFFIX 406 407 LOGO_IMAGE_FILENAME 408 IMAGE_REF 409 META_TAGS 410 411=cut 412 413 my ($line, $OPT) = @_; 414 my @KW = qw( 415 TXT_CONTENTS 416 TXT_INDEX 417 PAGE_CNT 418 TITLE 419 BASE_LEFT_TXT 420 BASE_RIGHT_TXT 421 BASE_MIDDLE_TXT 422 BOT_LEFT_TXT 423 BOT_RIGHT_TXT 424 BOT_MIDDLE_TXT 425 TOP_LEFT_TXT 426 TOP_RIGHT_TXT 427 TOP_MIDDLE_TXT 428 429 BGCOLOR 430 FGCOLOR 431 BOT_BGCOLOR 432 TOP_BGCOLOR 433 IDX_BGCOLOR 434 TOC_BGCOLOR 435 BOT_FGCOLOR 436 TOP_FGCOLOR 437 IDX_FGCOLOR 438 TOC_FGCOLOR 439 LINKCOLOR 440 TOP_LINKCOLOR 441 BOT_LINKCOLOR 442 TOC_LINKCOLOR 443 IDX_LINKCOLOR 444 ALINKCOLOR 445 TOP_ALINKCOLOR 446 BOT_ALINKCOLOR 447 TOC_ALINKCOLOR 448 IDX_ALINKCOLOR 449 VLINKCOLOR 450 TOP_VLINKCOLOR 451 BOT_VLINKCOLOR 452 TOC_VLINKCOLOR 453 IDX_VLINKCOLOR 454 455 LABEL_NEXT 456 LABEL_PREV 457 LABEL_INDEX 458 LABEL_CONTENTS 459 460 SLIDE_PREFIX 461 SLIDE_SUFFIX 462 463 LOGO_IMAGE_FILENAME 464 IMAGE_REF 465 META_TAGS 466 467 ); 468 $line =~ s/SLIDE_PREFIX/$$OPT{slide_prefix}/g; 469 # special word boundary for SLIDE_PREFIX ... 470 foreach my $kw (@KW){ 471 $line =~ s/\b$kw\b/$$OPT{lc($kw)}/g if defined $$OPT{lc($kw)}; 472 } 473 return $line; 474 475} # replace_keywords }}} 476 477sub copy_file { #{{{ ----------------------------------------------- 478 479=head2 copy_file($from, $to, $verbose, $KEY_HASH_REF); 480 481Copy file C<$from> to file C<$to>. For binary files (! -T) the File::Copy 482method will be used. Text files are copied by reading from 483C<$from> and printing to C<$to>. All lines are 484treated with the C<replace_keywords> method. 485 486Prints a message to STDERR if $verbose is set to 1. 487 488=cut 489 490 # should work on each system ... 491 my ($from, $to, $verbose, $OPT) = @_; 492 print STDERR "... copying $from to $to\n" if $verbose; 493 if (! -T $from){ 494 copy($from, $to); # (use correct mode for binary files) 495 } else { # should be text file ... 496 open(FROM, "< $from") or die "Can't open $from: $!\n"; 497 open(TO , "> $to") or die "Can't open $to: $!\n"; 498 while(<FROM>) { 499 print TO replace_keywords($_, $OPT); 500 } 501 close(FROM); close(TO); 502 } 503} # copy_file }}} 504 505sub update_file { #{{{ --------------------------------------------- 506 507=head2 update_file($from, $to, $verbose, $KEY_HASH_REF, $moveFlag); 508 509Update file C<$from> to file C<$to> if necessary. For binary files (! -T) 510the File::Copy method will be used. Files are only copied if the 511modification date of C<$to> is older than the modification date of C<$from>. 512 513Text files are B<always> copied by reading from 514C<$from> and printing to C<$to> because keywords might have 515changed. All lines are treated with the C<replace_keywords> method. 516 517Prints a message to STDERR if $verbose is set to 1. 518 519The source file is removed if the $moveFlag was set to a true value, 520which means that the function performs a move instead of a copy. 521 522=cut 523 524 my ($from, $to, $verbose, $OPT, $move) = @_; 525 # check, if update is really needed: 526 return if $to eq $from; 527 if (! -e $from) { 528 croak "\n**** file not found: $from\n"; ## should not occur! 529 } 530 # copy: 531 if (! -T $from){ # binary file ? 532 if (-e $to){ 533 my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$time2) = stat(_); 534 my $time1; 535 ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$time1) = stat($from); 536 return if $time1 <= $time2; 537 } 538 print STDERR "... copying $from to $to\n" if $verbose; 539 copy($from, $to); # (use correct mode for binary files) 540 } else { # should be text file ... 541 ## always copy, because the keywords might have changed ! 542 print STDERR "... copying $from to $to\n" if $verbose; 543 open(FROM, "< $from") or die "Can't open $from: $!\n"; 544 open(TO , "> $to") or die "Can't open $to: $!\n"; 545 while(<FROM>) { 546 print TO replace_keywords($_, $OPT); 547 } 548 close(FROM); close(TO); 549 } 550 551 # delete file, if necessary 552 unlink($from) if defined($move) and $move; 553} # update_file }}} 554 555sub return_abs_path { #{{{ ----------------------------------------- 556 557=head2 $abs_path = return_abs_path($pathname) 558 559Given a relative or absolute pathname: return absolute pathname 560$pathname must exist and either be absolute or relative to 561current working directory. 562 563=cut 564 565 my $path = shift; 566 my $cwd = cwd; 567 chdir $path or croak "Cannot cd to $path\n"; 568 my $abspath = cwd; 569 chdir $cwd or croak "Cannot cd back to $cwd\n"; 570 return $abspath; 571} # return_abs_path }}} 572 573sub is_abs_path { #{{{----------------------------------------------- 574 575=head2 is_abs_path($pathname) 576 577Return 1 if $pathname is an absolute pathname, i. e. it starts with 578a slash "/" or with a character, followed by a colon and and a slash 579or backslash: "C:/bla bla" or "T:\foo\bar". Otherwise return 0. 580 581=cut 582 583 my $path = shift; 584 return 1 if 585 $path =~ m#^\s*/# or 586 $path =~ m#^\s*[a-z]:[/\\]#i; 587 return 0; 588} # is_abs_path }}} 589 590sub relative_path { #{{{-------------------------------------------- 591 592=head2 $rel_path = relative_path($path1, $path2) 593 594Return relative path from $path1 to $path2. 595 596 path C:/this/is/my/test/foo 597 path2 C:/this/is/my/test/images/new 598 ==> rel_path ../images/new 599 600=cut 601 602 my ($path1, $path2) = @_; 603 my $rel = ""; 604 my ($p1, $p2) = ("$path1/", "$path2/"); 605 606 if (! is_abs_path($path1)){ 607 if (-d $path1) { 608 $p1 = return_abs_path($path1) . "/"; 609 } else { 610 # try to construct abs path: 611 $p1 = cwd() . "/$path1/"; 612 } 613 } 614 if (! is_abs_path($path2)){ 615 if (-d $path2) { 616 $p2 = return_abs_path($path2) . "/"; 617 } else { 618 # try to construct abs path: 619 $p2 = cwd() . "/$path2/"; 620 } 621 } 622 623#print "p1: $p1\n"; 624#print "p2: $p2\n"; 625 # reduce multiple / and \ to single / 626 $p1 =~ s#[\\]+#/#g; 627 $p1 =~ s#/+#/#g; 628 $p2 =~ s#[\\]+#/#g; 629 $p2 =~ s#/+#/#g; 630#print "1 p1: $p1\n"; 631#print "1 p2: $p2\n"; 632 return "." if uc($p1) eq uc($p2); 633 634 635# First: cut common part of pathname 636 while($p1 and $p2){ 637 my $h1 = ""; 638 my $h2 = ""; 639 if ($p1 =~ m#([^/]+)/#){ 640 $h1 = $1; 641 } 642 if ($p2 =~ m#([^/]+)/#){ 643 $h2 = $1; 644 } 645#print "11 h1: $h1\n"; 646#print "11 h2: $h2\n"; 647 if (uc($h1) eq uc($h2)){ 648 # is ok for windows and should work under UNIX as long as 649 # there are not two different dir names which are only distinct in 650 # letter case 651 substr($p1, 0, length($h1)+1) = ""; # cut leading part/ 652 substr($p2, 0, length($h2)+1) = ""; # cut leading part/ 653 } else { 654 last; 655 } 656#print "11 p1: $p1\n"; 657#print "11 p2: $p2\n"; 658 } 659#print "2 p1: $p1\n"; 660#print "2 p2: $p2\n"; 661# Second: construct relative pathname from $p1 to $p2: 662# go up from $p1 to common root: 663 $p1 =~ s#^/##; 664 $p2 =~ s#^/##; 665 while(index($p1, "/")>=0){ 666#print "33 p1: $p1\n"; 667 $rel .= "../"; 668 substr($p1, 0, index($p1,"/")+1) = ""; 669 } 670# append path to $p2 671 $rel .= $p2; 672 $rel =~ s#/$##; 673#print "---rel: $rel\n"; 674 return $rel; 675} # relative_path }}} 676 677=head1 AUTHOR 678 679Lorenz Domke <lorenz.domke@gmx.de> 680 681 682=cut 683 6841 685 686__END__ 687 688# vim:foldmethod=marker:foldcolumn=4 689 690