# Blosxom Plugin: blox # Author: Stu MacKenzie # Version: v0.97b 2004-09-05 (17) # License: MIT/Public Domain # blox home: http://www.enilnomi.net/download.html # Documentation at the bottom of this file or type: perldoc blox # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # The blox plugin saves you typing time by adding "paragraph" # markup tags around blocks of plain text as your entry files # are processed by Blosxom. When typing your entries, just # separate paragraphs by at least one blank line (completely # blank; no spaces, tabs, etc.) and blox will do the rest. # # Of course, you're free to use markup in your entries; blox # won't change any of your existing tags. However, in cases # where you have a tag at the start or end of a block (such # as "" or ""), you must add a single space character # before or after the tag to get blox to add its open- or # close-paragraph tag. # # Read the documentation at the end of this file for complete # details on all blox features/settings. New features in this # version include: breaking on single lines; ignoring complete # directories; un-ignoring directories and files; ignoring # stories handled by other formatting plugins; built-in markup # notation system; and correct handling of
 blocks.
#
#  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -


package blox;

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
#
#  Configuration Section
#
# # # # # # # # # # # # # # # # #
#
#  Open and Close tags --
#   The text entered between the single quote marks for $open_p_tag 
#   and $close_p_tag becomes the exact tags inserted before and after 
#   each untagged block of text in your entry files. "Normal" tags 
#   would be '

' and '

' $open_p_tag = '

'; $close_p_tag = '

'; # # Initial and final tags -- # If your story flavour templates specify a tag for the very # beginning or the very end of your entries, you can stop blox # from adding either tag by setting add_initial_open_tag # and/or add_final_close_tag to 0 [zero] # # Should blox place an open-tag at the start of the very first block? # 0 = no; 1 = yes (normal is yes) $add_initial_open_tag = 1; # # Should blox place a close-tag at the end of the very last block? # 0 = no; 1 = yes $add_final_close_tag = 1; # # # # # # # # # # # # # # # # # # # Breaking single lines -- # Should blox throw a break between single lines? # 0 = no; 1 = yes (normal is yes) my $break_singles = 1; # # What html tag should be used for these breaks? # (could be '
  • ' or '
    ' or '
    ' or plain old '
    ') my $break = '
    '; # # # # # # # # # # # # # # # # # # # Simple styling -- # Should blox use some simple wiki-like styling? # 0 = no; 1 = yes my $styles_active = 0; # # # # # # # # # # # # # # # # # # # Ignoring files or directories -- # blox will ignore any story whose first line is set to # '' (no quotes). You can also set files or # directories to ignore by entering paths into a file named # 'noblox' (no quotes) located in Blosxom's plugins state # directory. If you don't plan to use a noblox file, a # setting of 0 (zero) will save your server a bit of work # # If you don't plan to use a noblox file, a setting # of 0 (zero) will save your server a bit of work # # Should blox take the time to read a list of files to skip over? # 0 = no; 1 = yes $use_noblox_file = 1; # # # What's the complete path to the noblox file? # (leave empty for automatic configuration using Blosxom's plugins state dir) $noblox_file_path = ""; # # # # # # # # # # # # # # # # # # # Playing nice with other plugins -- # Should blox automatically ignore entries that set a value # for meta-markup via the meta plugin? # 0 = no; 1 = yes (normal is yes) my $skip_textile = 1; # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # sub start { !$use_noblox_file and return 1; # is this trip necessary? !$noblox_file_path and $noblox_file_path = "$blosxom::plugin_state_dir/noblox"; # read the whole file into a string open(NOBLOX, "< $noblox_file_path") or 1; my $str = join '', ; close(NOBLOX); $str =~ s/\r\n|\r/\n/gm; # make it proper lines @skips = (); # files to ignore @keeps = (); # files to un-ignore foreach (split /\n/, $str) { !$_ or /^\s*#/ and next; # skip empty lines and comments # keeps array gets lines that ^! ; (s/^!// and push(@keeps, "$blosxom::datadir/$_")) or push(@skips, "$blosxom::datadir/$_"); # skips array gets everything else } 1; } sub filter { my ($pkg, $files_ref) = @_; !$use_noblox_file and return 0; # is this trip necessary? %blox_skip_files = (); foreach $skip (@skips) { # each entry file path that qualifies as foreach (keys %$files_ref) { # a skip is given a key in the skips hash; /^$skip/ and $blox_skip_files{$_}=1; # that key is given a true value } } foreach $keep (@keeps) { foreach (keys %blox_skip_files) { # each entry file path key that qualifies /^$keep/ and $blox_skip_files{$_}=0; # as a keep has its value set to false } } 1; } sub story { my ($pkg, $path, $filename, $story_ref, $title_ref, $body_ref) = @_; # Blosxom expects \n line-endings (ascii 10), but macs might use # \r (ascii 13), and windows might use \r\n (ascii 13,10). # Macs will have the entire story in $title; Wins will leave # a trailing \r in $title. if ($$title_ref =~ s/\r\n?/\n/) { # change first foreign line end in $title to \n... ($$title_ref, my $temp) = split /\n/, $$title_ref, 2; $$body_ref = $temp . $$body_ref; # ...and re-populate the two vars } if ($$body_ref =~ m/\r/) { $$body_ref =~ s/^(?:(\r\n?)+)/\n\n/; # convert leading line-ends to double newline, $$body_ref =~ s/\r\n|\r/\n/gm; # and convert winlines and maclines # -- OR is this faster? -- #$$body_ref =~ s/\r\n?/\n/gm; } # 3 chances to ignore this file: # - automatic ignore $skip_textile and $blosxom::meta::markup and $blosxom::meta::markup ne 'blox' and return 0; # - noblox comment in entry file: $$body_ref !~ s/^$//mi or return 0; # - noblox file $use_noblox_file and $blox_skip_files{"$blosxom::datadir$path/$filename.$blosxom::file_extension"} and return 0; # Set up for styling: # the def from Kwiki.pm 0.18 wasn't $WORD = "A-Za-z0-9!\xc0-\xff_"; # cuttin' it; back to tried and true # preformatted, step 1 of 2 my $pre_mark = rand(7); # get a value that's unique to the text while ($$body_ref =~ m/$pre_mark/) {$$pre_mark += rand(7);} my %pre_storage = (); $i = 0; # replace PRE tags with our mark... while ($$body_ref =~ s/(\n?.*?<.*?\/pre>)/$pre_mark/si) { $i++; $pre_storage{$i} = $1; # ...and save the replaced text } # do some stylin': if ($styles_active) { # pre-treat all links $$body_ref =~ s#((?:https?|ftp|irc):)(/{0,2})(\S*?)#$1$3#g; for (my $i=1;$i<7;$i++) { # heads $$body_ref =~ s#(?$1\n#gm; } $$body_ref =~ s#(?\n#gm; # rules $$body_ref =~ s#^!(?=[=-])##gm; # escape heads and rules } # remove leading and trailing blank lines; # remember that it happened $have_starting_blanklines = $$body_ref =~ s/^\n+//s; $have_ending_blanklines = $$body_ref =~ s/\n+$//s; $$body_ref =~ s/\n{2,}/\n\n/gm; # eat surplus blank lines ## one user reports that "(?!\<)" fails in static mode # change untagged start-of-blocks $$body_ref =~ s/\n\n(?:(?!\<))/\n\n$open_p_tag\n/gm; # (except start of first block) # change untagged end-of-blocks $$body_ref =~ s/(?:(?))\n\n/\n$close_p_tag\n\n/gm; # (except end of last block) # break single lines if allowed $break_singles and $$body_ref =~ s/(?)\n(?![<|\n])/$break\n/gm; # change first untagged start-of-block if allowed ($add_initial_open_tag) && ($$body_ref =~ s/^(?:(?!<))/$open_p_tag\n/s); # change last untagged end-of-block if allowed ($add_final_close_tag) && ($$body_ref =~ s/(?:(?))$/\n$close_p_tag/s); # do some stylin': if ($styles_active) { # bold $$body_ref =~ s#(?$1#g; # italic $$body_ref =~ s#(?$1#g; # underline $$body_ref =~ s#(?$1#g; # escape *, /, _ $$body_ref =~ s#\!(?=[\*/_])##g;; # code $$body_ref =~ s#(?$1$2#gs; # raw links $$body_ref =~ s#(?$2#g; # named links $$body_ref =~ s#(?$1#gm; # escape [=], [http:], [named http:] $$body_ref =~ s#\!(?=\[)##g; # restore "normal" links $$body_ref =~ s#((?:https?|ftp|irc):)([^/])#$1//$2#g; } # restore leading/trailing blank line... ($have_starting_blanklines) && ($$body_ref =~ s/^/\n/); ($have_ending_blanklines) && ($$body_ref =~ s/$/\n/); # strip lone leading and trailing next-to spaces $$body_ref =~ s/($open_p_tag\n) (<)/$1$2/gm; $$body_ref =~ s/(>) (\n$close_p_tag)/$1$2/gm; ## (strip _consecutive_ spaces with: s/($open_p_tag\n) +?(<)/$1$2/gm;) $i = 1; # preformatted, step 2 of 2: restore replaced blocks while ($$body_ref =~ s/$pre_mark(?:$break)?/$pre_storage{$i}/) {$i++;} } 1; __END__ =head1 NAME Blosxom Plug-in: blox =head1 SYNOPSIS * Wraps pre-selected markup tags around "paragraphs" in plain text entry files; optionally adds pre-selected linebreak tags to single lines. * Doesn't interfere with existing markup, including
     tags
    
    * Gets out of the way of other formatting plugins (via meta).
    
    * Optionally translates simple markup codes into html tags for 
      heads, rules, bold, italic, underline, code, and links.
    
    * Config file or hard-wired story comments allow blox to ignore 
      directories and files; un-ignore allows great specificity.
    
    * Reads files from any text processor, recognizing Unix, Mac, and 
      Windows line ends.
    
    
    =head1 INSTALLATION
    
    UnZIP the file you downloaded; it becomes the "blox plugin for blosxom 2" 
    folder. Inside the folder, open the "blox" file and enter configuration 
    values per CONFIGURATION SECTION. Upload or drop this file into your 
    blosxom plugins folder. Blog on.
    
    
    =head1 CONFIGURABLE VARIABLES
    
    * Open and Close tags --
      The $open_p_tag and $close_p_tag variables become the exact markup 
      tags inserted before and after each block of text in your entry file. 
      Make sure you put your tags within single quotes, like this:
        $open_p_tag = '
    '; For "normal" html paragraph tags, use these values: $open_p_tag = '

    '; $close_p_tag = '

    '; * Initial and final tags -- The $add_initial_open_tag and $add_final_close_tag variables control whether blox adds an "open" tag at the very beginning of the entry, and a "close" tag at the very end of the entry. "1" adds the tag; "0" skips the tag. This is handy if your story templates provide an open- or close-block tag for entry files, for instance. However, most users will want to leave these settings at "1": $add_initial_open_tag = 1; $add_final_close_tag = 1; * Breaking single lines -- The $break_singles variable tells blox to add a tag at the end of single lines; the $break variable supplies the tag (normally
    ). When this is turned off (set to zero), the following entry file text line one line two line three will be rendered on your blog page as "line oneline twoline three". Most users will want these settings at "1" and "
    ": my $break_singles = 1; my $break = '
    '; (Make sure to put your break tag between single quotes) * Simple styling -- The $styles_active variable tells blox to use its simple markup system to automatically add tags for heads, rules, bold, italics, underline, code, and links. See the SIMPLE STYLING section below for details. * Ignoring files or directories -- The $use_noblox_file variable controls whether blox spends time reading a file named "noblox" to identify entries to ignore. "0" means "don't bother looking for a noblox file"; "1" means "read the noblox file and skip entries as it specifies." See USAGE (below) for "noblox" file details. Most users can leave this set at 1: $use_noblox_file = 1; * The $noblox_file_path variable holds the complete path to the "noblox" file; leave it blank to automatically configure using Blosxom's plugins state dir. If you supply a value here, make sure it's a complete path to the file; e.g. "$blosxom::datadir/my/own/state_dir/noblox" Most users should leave this value blank: $noblox_file_path = ""; * Playing nice with other plugins -- The $skip_textile variable lets you turn off the expected blox behavior of ignoring stories that contain a $meta::markup value. Most users should leave this value set to 1 my $skip_textile = 1; =head1 USAGE NOTE: if you are using the "blok" plugin, you should disable it; all of blok's functionality is built into blox. You can either delete blok, or change its name to "blok-" or " blok". Most posts are largely plain text, with just a few words using styles such as bold, italic, or underline. There might be some links, and maybe a blockquote or list, and that's about it. Using blox makes typing these entries easier by eliminating the need to type open- and close-block tags around individual "paragraphs" in your entry files. Optionally, blox will also put "break" tags after plaintext single lines. Of course, you're free to use markup in your entries; blox won't change any of your existing tags. However, in cases where you have a tag at the start or end of a block (such as "" or ""), you must add a single space character before or after the tag to get blox to add its open or close block tag. For example, the following entry text (everything between the double quotes) will produce a paragraph: " Do you see the leading space on this line? " while this entry text won't: "What's missing is a leading space on this line. " =head2 SIMPLE STYLING A simple markup notation for generating html tags is available by setting the $styles_active variable to 1. Notation rules are: *bold words* -- stars enclose words on single lines /italic words/ -- slashes enclose words on single lines _underlined words_ -- underscores enclose words on single lines [=monospaced words] -- "[=" can be anywhere; "]" can span lines [linked_http_url] -- brackets enclose single-line url, beginning with "htttp:", "ftp:", or "irc:" [named link http://url] -- brackets enclose single-line words and address; url begins with "http:", "ftp:", or "irc:" = Headline 1-6 -- equals sign(s) and one space preceed text at start of single line; the number of "=" sets the number of the "number" of the head; e.g. "= " yields H1 while "==== " yields H4. Equals signs can balance on the far side of the text; e.g. "=== Topic" is the same as "=== Topic ===". ---- -- four dashes at start of line followed by newline becomes HR ! -- exclamation point escapes ("negates") any of these effects by preceding the leading mark. Examples: *This* /works/ Th*is* /does/n't */This works/* *This _works_* *This /works*/ too [=this is code] [ftp://ftp.example.com] [named link http://www.example.com] *[bold named link http://www.example.com]* === An H3 Headline ---- (<-- a rule) Escaping: !---- <-- yields "----" !*No bold* <-- yields "*No bold*" !/No italics/ <-- yields "/No italics/" !_No underlines_ <-- yields "_No underlines_" ![=No monospace] <-- yields "[=No monospace]" !== Two Equals Signs <-- yields "== Two Equals Signs" ![http://example.com] <-- not a link; yields "[http://example.com]" ![No link http://example.com] <-- yields "[No link http://example.com]" The file "blox markup guide.txt" (in the "blox plugin for blosxom 2" folder) is a complete guide to blox markup notation. (It's also online at www.enilnomi.com/downloads/blox_markup_guide.txt) Set $styles_active to 1 in blox, and drop the file into your datadir; when you refresh your blog you'll see many samples of working and non-working markup. =head2 IGNORING FILES Certain machine-generated markup or oddball formatting can lead blox to add phantom paragraph tags to your rendered pages. In these cases, you'll want to tell blox to leave these entries alone. For entries you're typing in, the simplest method to get blox to ignore the file is to just enter at the start of any line in the story. You can also use a "noblox" file to tell blox which files to ignore. First, create a text file named "noblox" (no quotes) in Blosxom's plugins state directory. Then, enter in paths to files or directories that blox should ignore. If, within an ignored directory, there are files or directories that need blox, they can be un-ignored by listing their paths with a leading "!" (no quotes). Lines in the noblox file can themselves be ignored by adding a leading "#" (no quotes). Paths in the noblox file need to be formatted as follows: 1 - all paths start from where the Blosxom datadir leaves off 2 - no path begins with a slash (/) 3 - all directory paths end with a slash (/) For example, if your $blosxom::datadir is: /var/www/html/example.net/blosxom/docs and you want blox to ignore the story: www/example.net/blosxom/docs/tech/projects/time_machine.txt then your "noblox" entry for the file would look like this: tech/projects/time_machine.txt To have blox skip the whole /projects folder: tech/projects/ To have blox skip the whole somewhere.net/blosxom/docs/tech folder: tech/ If your $blosxom::datadir was: /Library/WebServer/Documents/blosxom then your "noblox" lines for the above example would look like this: docs/tech/projects/time_machine.txt docs/tech/projects/ docs/tech/ If certain files or directories within a noblox directory need to use blox, you can "un-ignore" them by prepending a "!" (no quotes) to their path. For example, let's say that everything in the /docs/tech directory could be ignored, except for the files in /docs/tech/projects directory. Your noblox entries would look like this: docs/tech/ !docs/tech/projects/ Now, every entry file in /docs/tech/programming and /docs/tech/news will be ignored, but the files in the /docs/tech/projects directory will be handled by blox. NOTE: a noblox comment within an entry file always "trumps" an unignore path in the noblox file. The best way to assess blox' compatibility with your existing entry files is to try it out; if entries don't look good, then adios, blox! (Remember: blox does nothing to your actual *files* -- any mistakes it makes with your entries appear only in Blosxom's output.) =head2 PREFORMATTED TEXT As of version 0.98 blox properly renders preformatted text blocks (text within
     tags); previous versions required most users to 
    make blox ignore files that contained PRE tags. Now, nearly no one 
    should have to ignore such files.      Huzzah.
    
    
    =head2 LINE ENDS
    The blox plugin reads line ends from Unix (ascii 10), Mac (ascii 13), and 
    Windows (ascii 10/13) with equal grace; use any text processor you like to 
    edit story files and noblox files.
    
    
    =head1 BUGS
    
    Address bug reports and comments to the Blosxom mailing list:
    http://www.yahoogroups.com/group/blosxom
    
    
    =head1 VERSION
    
    2004-09-05 (v0.97b) - stopped using unicode char set names (from kwiki 0.18), 
                          since some perls couldn't handle them; code cleanup
    2004-08-24 (v0.97a) - normal tagged links were being mangled; fixed
    2004-07-22 (v0.97)  - cleanup; add un-ignore, linebreaking, styles, graceful 
                          PREs; convert line-ends in noblox file
    2003-09-14 (v0.96)  - better line-end conversion
    2003-09-09 (v0.95)  - LOL! put Win line-end chars in correct order ;-)
    2003-08-31 (v0.94)  - add Mac and Windows line-ending conversion
    2003-08-30 (v0.93)  - wip
    2003-08-04 (v0.92)  - add mechanisms to ignore specified entries
    2003-07-31 (v0.9)   - half-fast workaround for 
     tags
    2003-07-20 (v0.8)   - it's alive
    
    =head1 LICENSE
    
    this Blosxom Plug-in
    Copyright 2003-2004, Stu MacKenzie
    
    Permission is hereby granted, free of charge, to any person obtaining a
    copy of this software and associated documentation files (the "Software"),
    to deal in the Software without restriction, including without limitation
    the rights to use, copy, modify, merge, publish, distribute, sublicense,
    and/or sell copies of the Software, and to permit persons to whom the
    Software is furnished to do so, subject to the following conditions:
    
    The above copyright notice and this permission notice shall be included
    in all copies or substantial portions of the Software.
    
    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
    OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
    ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
    OTHER DEALINGS IN THE SOFTWARE.