Developing Outreach 2 (requires XSL and HTML Tidy)

Posted on Fri, 7th July 2006 at 23:00 under Outreach, WordPress, Plugins, Web Standards

Wow! Another thought inspired by The Cathedral and The Bazaar, by Eric S. Raymond. This time, lessons 3 and 2. If you are not a geek, this post contains Outreach links especially for you.

Narrative

Now that libertus is hosted on a server under my complete control, I can pick and choose (and even compile) the components and services I want available to the blog. I am very fond of Outreach v0.5. As a piece of experimental and education code, it has served its purpose well, without fail, for many months. It has even evolved a primitive sense of style. See the source.

It’s time to throw it away and start again. This time, I have available the Turing complete XSL and the handy, if quirky, HTML Tidy. Outreach is a XML namespace, nothing more. The Outreach plugin for WordPress is nothing more than a simple but highly-specific XML document transformation, implemented using regular expressions and some crafty PHP.

Outreach 2 shall be a plugin for WordPress that transforms post and comment content using XSLT to implement the same well-defined (with DTD, perhaps) set of XML tags and their current behaviour, primaily the automatic generation of indirect links.

Additionally, I would like to offer a broader choice of entry syntaxes than XHTML and plain text. I like Markdown syntax but don’t like the WordPress plugin that implements it*. I am also interested by the syntax used on wikis such as the sublime Wikipedia, especially [[postname]], which I intend to use to ease the process of constructing internal links.

Requirements

  1. Re-engineer Outreach Content Filter Using XSLT
    Completed, the wrong way, Sunday 9th July 2006 at 18:00.
  2. Re-engineer Outreach Plugin for WordPress
  3. Implement XHTML Validation With HTML Tidy
  4. Explore Markdown and Wiki Syntaxes
  5. Test Locally
  6. Prepare Customised PHP
  7. Install Customised PHP on libertus
  8. Install Outreach 2 on libertus
  9. Integration Testing
  10. Launch

22 Responses

  1. Re-engineer Outreach Content Filter Using XSLT

    What made the first version of the Outreach plugin a challenging development was finding the tags, which involved my learning and using regular expressions. See the source.

    With XSLT, the tags are already found so all that is left to do is declare what I want done with them. Sweet.

    A Blank XSLT Page

    Every program begins with a blank page. A blank PHP page is gorgeously simple (<?php ?>). What about XSLT?

    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    </xsl:stylesheet>

    Nowhere near as simple but, I assure all you non-geeks, that is identical to the PHP, only far more specific. There is no chance of anyone or anything, especially not a computer, misunderstanding what is going on. I am especially pleased with the version declaration.

    Basic Content Filtering

    As I mentioned above, with XSLT, the tags are aleady found, so all I need to tell the program is what to do with them, if anything. Unless told otherwise, XSLT extracts all the text it can find in the input - not very useful. The first thing I need is an identity transformation or, in other words, copy the input unchanged directly to the output. If there are no Outreach tags in the content, the unchanged content can be the only correct output. XSLT has a well-defined, if somewhat complex, identity transformation pattern.

    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    
    <xsl:template match="@*|node()">
      <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
      </xsl:copy>
    </xsl:template>
    
    </xsl:stylesheet>

    Matching Outreach Tags - The Wrong Way

    There are two ways I can go about this; the wrong way and the right way. I am going to do both, starting with the former. It’s a bit much to expect do something the right way the first time.

    The Outreach tags in my content all have names prefixed with is:, both to differentiate them from the XHTML tags and to make them easier to read, remember and therefore use. The simplest tags I use a lot that are <is:uri @cite=URI @title=title @level=level>, to reference a specific webpage, and <is:thing @cite=citation @title=title @level=level @from=URI>, to reference an authoritative source (I use Wikipedia). The result of my embedding these tags in my content is that an automatic <a> link being generated, to the cited href in the former, and to the correct href for the Wikipedia page named after the citation, or some other href directly specified by the from attribute. See the source code.

    The simpler of the two tags I want to transform is the uri. So, I have to tell XSLT I want to do something with any such tag found.

    <xsl:template match="is:uri">
    </xsl:template>

    Yes, it’s that simple! So the problem is, what exactly do I want to do with this tag? Two things; leave it in the content unchanged, and wrap whatever the tag wrapped with a link, according to the cited URI. So, for my normal use <is:uri cite="http://somwhere">link to somewhere</is:uri> is transformed into <is:uri cite="http://somwhere"><a href="http://somwhere">link to somewhere</a></is:uri>.

    <xsl:template match="is:uri">
      <xsl:copy>
      <xsl:apply-templates select="@*"/>
      <xsl:element name="a">
        <xsl:attribute name="href"><xsl:value-of select="@cite"/></xsl:attribute>
        <xsl:value-of select="."/>
      </xsl:element>
      </xsl:copy>
    </xsl:template>

    Putting this all together gives me outreach-2/wrong-way-1.xsl. I do so hope that it does what I think it does. :) The only way to find out if a program works is to run (or execute) it. If this were a PHP program I could ask the shell to pass it as input to the PHP processor like so: php outreach-2/wrong-way-1.php but no such luck. XSL is a programming language for stylesheets, so the program I have written is not strictly standalone. As a transformation program, it acts on input to product output as part of a process. To get my output by running my program, I need two more things; input and an XSLT processor.

    For input, I shall use the markup for the parent post to this comment because it is chock-full of Outreach tags (copy-and-paste). A command-line XSLT processor is already installed on my Ubuntu Linux system (package xsltproc). Ask the shell to put everything together and…

    paul@kubuntu ~/s/l/w/projects> xsltproc –help
    Unknown option –help :D Libertus
    Usage: xsltproc [options] stylesheet file [file …]
    Options:
    –version or -V: show the version of libxml and libxslt used
    –verbose or -v: show logs of what’s happening
    … a lot of options
    –load-trace : print trace of all external entites loaded
    –profile or –norman : dump profiling informations

    Project libxslt home page: http://xmlsoft.org/XSLT/
    To report bugs and get help: http://xmlsoft.org/XSLT/bugs.html

    Oh boy, that’s a lot of options. Bugger that. Just go for it.

    paul@kubuntu ~/s/l/w/projects> xsltproc outreach-2/wrong-way-1.xsl outreach-2/wrong-way-1-test-data
    xsltCompileStepPattern : no namespace bound to prefix is
    compilation error: file outreach-2/wrong-way-1.xsl line 4 element template
    xsltCompilePattern : failed to compile 'is:uri'

    My program is wrong. I cannot get away without declaring to the XSLT processor that I’m currently using is: to mean the Outreach tag namespace, in the same way that xsl: is bound to the XSL namespace. I directly copy the namespace declaration from the blog page source.

    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
    xmlns:is="http://libertini.net/libertus/outreach/">
    paul@kubuntu ~/s/l/w/projects> xsltproc outreach-2/wrong-way-1.xsl outreach-2/wrong-way-1-test-data
    outreach-2/wrong-way-1-test-data:1: parser error : Start tag expected, '<' not found
    Wow! Another thought inspired by <is:uri cite= "http://www.catb.org/~esr/writing^
    unable to parse outreach-2/wrong-way-1-test-data

    Hmmm… seems my test data isn’t tidy enough for the XSLT processor. No problem. Rather than change the test data, I can process it with HTML Tidy and provide the tidied output to the processor instead. I love the command line. What does tidy have to say about my test data?

    paul@kubuntu ~/s/l/w/projects> tidy -q -clean -asxhtml outreach-2/wrong-way-1-test-data
    line 1 column 1 - Warning: missing <!DOCTYPE> declaration
    line 1 column 1 - Warning: plain text isn't allowed in <head> elements
    line 1 column 34 - Error: <is:uri> is not recognized!
    line 1 column 34 - Warning: discarding unexpected <is:uri>
    line 1 column 130 - Warning: discarding unexpected </is:uri>
    line 1 column 172 - Error: <is:uri> is not recognized!
    line 1 column 172 - Warning: discarding unexpected <is:uri>
    line 1 column 195 - Warning: discarding unexpected </is:uri>
    line 1 column 223 - Error: <is:thing> is not recognized!
    line 1 column 223 - Warning: discarding unexpected <is:thing>
    line 1 column 237 - Warning: discarding unexpected </is:thing>
    line 7 column 77 - Error: <is:concept> is not recognized!
    line 7 column 77 - Warning: discarding unexpected <is:concept>
    line 7 column 121 - Warning: discarding unexpected </is:concept>
    line 7 column 135 - Error: <is:product> is not recognized!
    line 7 column 135 - Warning: discarding unexpected <is:product>
    line 7 column 253 - Warning: discarding unexpected </is:product>
    line 7 column 293 - Error: <is:product> is not recognized!

    Double hmmm…! HTML Tidy is refusing to do its job because it doesn’t recognise the tags I want the XSLT processor to transform for me! No problem - I’ll just have to tell Tidy about my Outreach tags, using the new-inline-tags configuration option.

    paul@kubuntu ~/s/l/w/projects> tidy -q -clean -asxhtml –new-inline-tags is:uri,is:thing,is:concept,is:product,is:word outreach-2/wrong-way-1-test-data
    line 1 column 1 - Warning: missing <!DOCTYPE> declaration
    line 1 column 1 - Warning: plain text isn't allowed in <head> elements
    line 1 column 34 - Warning: <is:uri> is not approved by W3C
    line 1 column 172 - Warning: <is:uri> is not approved by W3C
    line 1 column 223 - Warning: <is:thing> is not approved by W3C
    line 7 column 77 - Warning: <is:concept> is not approved by W3C
    line 7 column 135 - Warning: <is:product> is not approved by W3C
    ...
    line 7 column 804 - Warning: <is:thing> is not approved by W3C
    line 7 column 878 - Warning: <is:product> is not approved by W3C
    line 9 column 137 - Warning: <is:thing> is not approved by W3C
    line 11 column 63 - Warning: <is:word> is not approved by W3C
    line 11 column 113 - Warning: <is:product> is not approved by W3C
    line 11 column 243 - Warning: <is:thing> is not approved by W3C
    line 11 column 300 - Warning: <is:product> is not approved by W3C
    line 11 column 356 - Warning: <is:product> is not approved by W3C
    line 11 column 522 - Warning: <is:thing> is not approved by W3C
    line 11 column 577 - Warning: <is:thing> is not approved by W3C
    line 11 column 577 - Warning: replacing unexpected is:uri by </is:uri>
    line 11 column 759 - Warning: <is:uri> is not approved by W3C
    line 1 column 1 - Warning: inserting missing 'title' element
    line 7 column 135 - Warning: <is:product> escaping malformed URI reference
    ...
    line 11 column 522 - Warning: <is:thing> escaping malformed URI reference

    Tidied test data follows

    Yeah, yeah, yeah! Indeed, Outreach is not approved by the W3C. Many warnings, but no errors, so I get what I want - a clean and tidy XHTML file that I can pass into the XSLT processor. Tidy even fixed a mistake in my markup with an Outreach tag - line 11, column 577. What a wonderful tool! Unfortunately, Tidy did not copy across my namespace declaration, so the XSLT processor still cannot understand the input. I’ll have to process the output from Tidy, using the stream editor, to add the missing namespace to the input before the XSLT processor gets it.

    Wait! I know I’m going crazy when I think about using sed to do a job! I prefer PHP, which can do the tidying, replace the <html> tag line and run the XSLT processor. I’ll write a program called wrong-way-1.php that pulls everything together.

    Success. A simple is:uri.

    Reply
  2. Continued Wrongdoing

    Yesterday I began with nothing and ended the day with a minor success - a single, specific form of an Outreach tag being rendered, albeit the wrong way. Today my intention is to expand the repertoire of the new Outreach XSL content filter to cover all the tags I have previously defined, their attributes and respective link generators.

    But first, I shall complete the implementation of the is:uri tag so that it is perfectly wrong. I can then copy that code to speed the implementation of the others.

    Perfecting is:uri

    There’s one thing left to do with is:uri - draw the citation URI from the text if no cite attribute is specified. That requires a conditional expression in the transformation program, simply if cite given, use that otherwise use the text.

    Yesterday’s transformation program for is:uri is as follows:

    <xsl:template match="is:uri">
      <xsl:copy>
      <xsl:apply-templates select="@*"/>
      <xsl:element name="a">
        <xsl:attribute name="href"><xsl:value-of select="@cite"/></xsl:attribute>
        <xsl:value-of select="."/>
      </xsl:element>
      </xsl:copy>
    </xsl:template>

    The problem with this is that should there be no cite attribute, the link is generated with an empty href. Not for long.

    
      <xsl:element name="a">
        <xsl:attribute name="href">
          <xsl:choose>
            <xsl:when test="@cite"><xsl:value-of select="@cite"/></xsl:when>
            <xsl:otherwise><xsl:value-of select="text()"/></xsl:otherwise>
          </xsl:choose>
        </xsl:attribute>
        <xsl:value-of select="."/>
      </xsl:element>
    

    The href attribute of the link is now generated thusly: when there is a cite attribute, use it, otherwise, use the element text.

    As I’m on the second day and I want to keep things in order, I’m creating a new set of files; test data, stylesheet and PHP script.

    Reply
  3. It May Be Wrong, But It Works!

    I love days like this! Days where I get a little grin of pride. It irked me that the PHP script I have working locally didn’t work on the blog, so I fixed it. The result from yesterday’s work is now available.

    Reply
  4. Sustained, Willful Wrongdoing

    I do declare, that this here text refers to this here thing and this here link is how I would learn more about it.

    With is:uri nailed, time to move on to the rather more useful is:thing, which I use to link to the Wikipedia entry about something, just like that, or like that when the text isn’t the citation I’m making, or, on rare occasions, like this when Wikipedia isn’t an authority.

    The transformation is pretty simple. The generated link is http://en.wikipedia.org/wiki/ followed by the citation. There is one snag though. Wikipedia likes underscores instead of spaces, and multi-word citations are separated by spaces. So, a little text transformation is also required. Finally, the from attribute is supported by is:thing, which overrides the automatically generated href leaving both the text and citation intact.

    This XSL Thing Is Like So Random

    I start with a copy of the template for is:uri, altered accordingly. The from attribute was already implemented by the is:uri cite attribute, so it just gets renamed. If there is no from attribute, either the citation or the text must be transformed into a Wikipedia URL, somehow. I used the PHP strtr() function the first time around. See the source.

    My first cut, without any attempt to translate the citation for Wikipedia, is as follows. I’m starting to really like XSLT. It is ugly but elegant, like a certain someone I know. :)

    <xsl:template match="is:thing">
      <xsl:copy>
        <xsl:apply-templates select="@*"/>
        <xsl:element name="a">
          <xsl:attribute name="href">
            <xsl:choose>
              <xsl:when test="@from"><xsl:value-of select="@from"/></xsl:when>
              <xsl:otherwise>
                <xsl:text>http://en.wikipedia.org/wiki/</xsl:text>
                <xsl:choose>
                  <xsl:when test="@cite"><xsl:value-of select="@cite"/></xsl:when>
                  <xsl:otherwise><xsl:value-of select="text()"/></xsl:otherwise>
                </xsl:choose>
              </xsl:otherwise>
            </xsl:choose>
          </xsl:attribute>
          <xsl:value-of select="."/>
        </xsl:element>
      </xsl:copy>
    </xsl:template>

    Hmmm… what are those newlines (&#10;) doing in my hrefs? It’s coming from the text() function. I need to make sure that kind of whitespace is stripped out. Hmmm… I read the XPath documentation and find the likely-looking core function normalize-space().

    <xsl:otherwise><xsl:value-of select="normalize-space(text())"/></xsl:otherwise>

    Nearly there. I’m sure XPath also offers a character translation function.

    <xsl:when test="@cite"><xsl:value-of select="translate(@cite,' ','_')"/></xsl:when>
    <xsl:otherwise><xsl:value-of select="translate(normalize-space(text()),' ','_')"/></xsl:otherwise>

    Hmm… %20 in a citation doesn’t match a space character, no surprise. I need to disable the fix-uri HTML Tidy configuration option. That does it.

    Success. is:thing now supported. Perhaps it is time to add a little style, to show what is going on.

    is:uri a { border-bottom: 2px solid green; }
    is:thing a { border-bottom: 2px solid red; }

    Hmmm… styling with namespaces doesn’t seem to work. Generated links need to have a class anyway, so I’ll go with what I did before (class=outreach) and add a rel attribute set to the element name. This lets me write some simple but classy CSS.

    body { line-height: 150%; }
    a.outreach { background: powderblue; }
    a.outreach[rel~='uri'] { border-bottom: 2px solid green; }
    a.outreach[rel~='thing'] { border-bottom: 2px solid red; }

    Done. Now for Google links.

    Reply
  5. Deliberate, Wrongful Use Of Google

    I do declare, that this here text refers to this here concept, person, product or corporation. If you want to learn more, Google will take you there, unless my link is better.

    A secondary purpose of Outreach is to combat link rot by linking indirectly through Google. The most relevant page on a particular subject today may not be so relevant next week, even if the URL has not changed. Google sets an impressive quality standard for directing people to the most relevant website for a particular concept, say search engine optimisation. Google also works well for famous people, such as Armageddon T. Thunderbird, products such as Ozric Tentacles and corporate bodies such as The Government of the United States of America. Even money Google has trouble with the last one.

    There is absolutely nothing special about these tags. They all generate Google I’m Feeling Lucky links to their citations. I copy from the is:thing template and adjust accordingly. I have to calculate the rel attribute and Google doesn’t need the citation translated like Wikipedia.

    <xsl:template match="is:concept|is:person|is:product|is:corp">
      <xsl:copy>
        <xsl:apply-templates select="@*"/>
        <xsl:element name="a">
          <xsl:attribute name="class">outreach</xsl:attribute>
          <xsl:attribute name="rel">
            <xsl:value-of select="substring-after(name(),':')"/>
          </xsl:attribute>
          <xsl:attribute name="href">
            <xsl:choose>
              <xsl:when test="@from"><xsl:value-of select="@from"/></xsl:when>
              <xsl:otherwise>
                <xsl:text>http://www.google.com/search?btnI=I'm feeling lucky&q=</xsl:text>
                <xsl:choose>
                  <xsl:when test="@cite"><xsl:value-of select="@cite"/></xsl:when>
                  <xsl:otherwise><xsl:value-of select="normalize-space(text())"/></xsl:otherwise>
                </xsl:choose>
              </xsl:otherwise>
            </xsl:choose>
          </xsl:attribute>
          <xsl:value-of select="."/>
        </xsl:element>
      </xsl:copy>
    </xsl:template>

    Add a bit more style; concepts are solid gold, people are brown, products are silver and corporations are black. Presto!

    Reply
  6. Proper Use Of Google

    I do declare, that this here text refers to this here search. I hope you find what you need.

    is:search is so simple that I won’t bother repeating the code here. Remarkably like the previous one, only less confident.

    I do declare, that this is a real word and I know what it means. If you don’t believe me, here’s a link to the dictionary definition!

    is:word is also too simple to repeat. It’s just a Google search on define:$citation.

    As I decided to merge the two into a single template, I’ll repeat the code here. Why not? Part of doing things the wrong way is to learn from mistakes, especially the simple ones.

    <xsl:template match="is:search|is:word">
      <xsl:copy>
        <xsl:apply-templates select="@*"/>
        <xsl:element name="a">
          <xsl:attribute name="class">outreach</xsl:attribute>
          <xsl:attribute name="rel"><xsl:value-of select="substring-after(name(),':')"/></xsl:attribute>
          <xsl:attribute name="href">
            <xsl:choose>
              <xsl:when test="@from"><xsl:value-of select="@from"/></xsl:when>
              <xsl:otherwise>
                <xsl:text>http://www.google.com/search?q=</xsl:text>
                <xsl:if test="name()='is:word'"><xsl:text>define:</xsl:text></xsl:if>
                <xsl:choose>
                  <xsl:when test="@cite"><xsl:value-of select="@cite"/></xsl:when>
                  <xsl:otherwise><xsl:value-of select="normalize-space(text())"/></xsl:otherwise>
                </xsl:choose>
              </xsl:otherwise>
            </xsl:choose>
          </xsl:attribute>
          <xsl:value-of select="."/>
        </xsl:element>
      </xsl:copy>
    </xsl:template>

    Add a bit of style (blue for search and yellow for word), twiddle the test data to include a is:search and… here they are. Almost done.

    Reply
  7. A Final Act Of Wrongness

    Only two tags left, and they are trivial. is:place has the same implementation as is:thing and is:money has no implementation (although I have thought of a few), so just needs to be accommodated for the moment.

    I do declare, the first step is complete.

    Reply
  8. Re-engineer Outreach Plugin For WordPress

    With a content filtering solution proven, I turn my attention to the difficult second step - turning it back into a plugin for WordPress, without losing any function.

    Outreach Plugin For WordPress, version 0.5, Functional Review

    The Outreach Plugin does just a little more than link generation. It also provides a control panel for the reader, who may choose from a menu of available outreach settings; removing the links entirely, revealing hidden links and returning to the default links. A control panel appears inside any block of content that contains outreach tags, providing an anchor to which the menu links refer back. See the source.

    Finally, the plugin provided a rudimentary validation service during post editing, warning of imbalanced tags, which was broken in WordPress 2.0 by the snazzy new Post Preview feature.

    Outreach Plugin For WordPress, version 2, Functional Specification

    Function

    Specification
    Activation Hook
    Check that machine is capable of running the plugin. Look for XSL, Tidy etc.. Helpful messages with links should required components be missing.
    Post and Comment Content Save
    Validate content with HTML Tidy (unless forced not to), and on-demand. Refuse to save if errors in content, allow save on warnings (filtering out those that are a by-product of the validation process itself), offer clean and repair service (do not force)
    Content Filter
    Light linear scan for occurrence of outreach tag prefix to trigger heavy text->DOM->XSL->DOM->text sequence.
    Content DOM load failure (invalid content) indicated by marker prepended to text.
    XSL processor prepared once
    Processor performs link generation and control panel generation according to query string parameter outreach, including off.
    Reply
  9. Outreach Plugin, version 2, Technical Specification

    The Outreach plugin, version 2, provides three primary functions;

    • Systems OK Check,
    • Content Validation (with HTML Tidy), and
    • Content Filtering (with XSLT)

    An integration layer is required for each particular CMS.

    Systems OK Check

    Two modes; quick or complete. The default is complete. Boolean response.

    Quick
    Only check versions and class existence.
    Complete
    As for quick and attempt to load classes

    Make human and other diagnostic information available for systems not OK.

    Content Validation

    This is a suite of services, oriented around one data structure, streams of text, and one library, HTML Tidy.

    The intended use case is that a person has prepared a stream of text content containing markup and they want to save it in the database, with a presumption of validity. The function is therefore the validity checking of a stream of text with boolean response, the provision of validity diagnostics, with optional provision of a repaired or beautified text stream.

    The incoming text is assumed to be a fragment of rather than a complete document, so is placed in a valid skeleton document (using DOM if possible) before being passed to Tidy, which then only has to return the body. If there are no errors, return the original content, unless beautification or repair explicitly requested.

    Make human and other validation diagnostics available.
    Make SHA1 hash of returned valid content avaiable.

    Content Filtering

    This is a single function, processing a text stream though XSL to add Outreach links and a control panel. All calls made to this function are presumed to be for a single page of content unless indicated otherwise. A parameter level, intended to be provided by the reader through the query string, controls the filter. The control panel provides these links.

    Level
    Effect
    X (off, no)
    No operation. Content returned unaltered.
    0 (-, none)
    Add control panel only, no link generation
    1 (=, on, default, not specificed)
    Control panel, all primary (closest) tags without levels rendered
    +$level-tag-or-type
    Include tags with specified level, on its own shows all
    -$level-tag-or-type
    Exclude tags with specified level, on its own excludes all
    =$level-tag-or-type
    Only tags with specified level

    Move the closest outreach tag title attribute into the generated link

    Control panel divisions (class outreach control-panel are sequentially id-numbered (outreach-control-panel-$n) and emitted before the content. It contains a link outreach to the help page, so entitled, an X off link, an unordered list of main level control links (none, default, all (if different from default), with optional sub-list of controls for levels found on tags in content. The title for control links state how many tags. All control links adjust the outreach query parameter only and include the fragment id of the containing control panel.

    Actual link generation should be handled by the integration layer. The default is ?outreach=$level#outreach-control-panel-$n.

    Generated links must not invalidate the content. Nested anchors are not allowed. In-line elements within generated links are valid and so must be allowed.

    The generated link destinations must be reader-configurable with host-provided defaults.

    Reply
  10. Outreach Plugin 2 Architechture Analysis

    Always seems to be a matter of taste, this part. All the libraries being used are object-oriented, the interface is simple and universal CMS integration seems to be possible.

    The plugin requires PHP 5 because it requires Tidy 2. The object system in PHP 5 is far better than in any previous version and seems to be the main aspect of PHP getting attention from the core developers. I’ve had difficulties mixing object syntax with array syntax, but do not anticipate the need to manipulate complicated data structures in the plugin code as all that crap is being handled by the libraries.

    An object architecture seems like a good fit. There is the Outreach Core, as described in the technical specification, which does the real work and is separated from the CMS by the Outreach Plugin, which gets and delivers the work.

    Each CMS requires an integration class, based on the Plugin class, for instance Outreach Plugin for WordPress.

    Reply
  11. Outreach Plugin 2 Programming - The Wrong Way

    I do declare, that the best way to lick a hard job is to get started.

    Formal software development systems tend to have a few more levels of paperwork before reaching this point in the project - writing the actual code. The benefit of doing things the wrong way (and not caring) is that it makes something real for people to play with and think about before committing to the rather more costly enterprise of developing it the right way.

    It’s a bit of a dice roll. If the wrong way is good enough, maybe the right way can be put off for a while. Maybe the wrong way will show that the right way is too costly, which is also good to know.

    Getting Started

    I already have a project directory and Subversion repository. It even contains a few files! I’ll create a plugin directory and put a blank PHP file called outreach2.php in it. And outreach2-core.php.inc. And outreach2-core.xsl.

    Started

    I have code that looks almost, but not entirely unlike a WordPress plugin. If I ran it, it would do nothing, although it would be working. Perhaps I should test that… perhaps not.

    Reply
  12. The Outreach2 Control Panel

    Having proven that tag rendering is easy, how challenging is constructing a useful little control panel from the tags themselves? Immediately, I can see that I need all the Outreach tags from the content being filtered. If there are none, the filter has no work to do and no control panel is required.

    <xsl:stylesheet
    	xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    	xmlns:is="http://libertini.net/libertus/outreach"
    	version="1.0">
    
    <xsl:template
    	match="is:*"
    	name="all-outreach-tags">
    </xsl:template>

    The Outreach content filter is defined by that template’s match, although an empty template would do the exact opposite of its intended function - strip out all the outreach tags. That’s worth a run against my test data. Create wrong-way-3.php, wrong-way-3.xsl and wrong-way-3-test-data. Contrast with the output from the previous wrong way script which uses the same test data. There are distinct signs of something being missing.

    Wow! Another thought inspired by , by Eric S. Raymond. This time, . If you are not a , this post contains Outreach links especially for you. ? What . :D

    What Was Removed?

    The template matches all outreach tags and does precisely bugger all with each one. If the template is going to take the tags, the least it can do is give back a count of how many were taken.

    
    
    Reply
  13. XSL Is A Frustrating Language

    Turing complete indeed! So is Brainfuck. Unfortunately, my brain is fucked, being naturally Turing incomplete. I’m left with is this feeling of stupidity. There are 27 Outreach tags in my test data. Now what?

    Oh well. There’s always tomorrow. :D And there’s always a fallback available to PHP.

    Reply
  14. Yesterday’s Frustration, Today’s …?

    I don’t want the types of the tags but I do want their level attributes. Each unique level is added to the list in the control panel, linked and titled accordingly. The control panel can be built as a result tree fragment in a variable and copied into the content where necessary.

    Reply
  15. Phew!

    Learning how a language works is hard work! I’ve studied XSLT enough and developed Outreach 2 enough to stop. There are other priorities and I think I’m able to take them on now.

    I’ll be back… :)

    Reply
  16. Question From Another Project

    Could the entirety of the Outreach tag language be expressed using <a>? If not, why not?

    Reply
  17. Wow, you could really use a plugin that allows authors to have threaded posts. That way you’re not using your comments to continue on with a thought or idea. :)
    I’ve been playing around with your idea. The only problem is your site — and any site I try your stuff with — doesn’t even come close to validating.
    So to me it seems like I can have either a valid site, or semantic site. Can’t have both.

    Reply
  18. Hi Sean,

    I miss you on IRC! You should be spending your time there instead of expanding your plugin portfolio!!

    Threaded posts? Yeah, I’d like that. I love to explore tangents and off-shoot ideas, which isn’t easy with a linear discussion format. I’m working on it, just not for WordPress, which isn’t designed to host serious discussions. I’m quite fond of the style used at theyworkforyou.com, which was designed to host serious discussions.

    As to validation, my site is standards-compliant - more so than the W3C validator. I mean, come on, who actually uses XML namespaces in web documents, so why bother considering them valid, or even worse, ignoring them? ;)

    Reply
  19. Go on, run this page by the W3C Markup Validator. A few errors on my part, lost in a sea of computer-generated errors. What a mess!

    Typing in raw XHTML isn’t easy. Markup is particularly susceptible to minor errors, such as the typo and the brain fart.

    Reply
  20. Hehe.. 68 errors is pretty significant. What gets me is declaring the is: namespace is apparently invalid — xmlns:is=”http://libertini.net/libertus/outreach/”>.

    I’ve been trying to avoid IRC. Nothing blows enormous amounts of my time more than #wordpress. :) It’s an addiction.

    A threaded posts plugin would be interesting. I picture something like GMail’s threaded emails thingy. You should email me sometime. I’ve been working on “minor” projects with friends that you might be interested in.

    Reply
    1. I’ve got threaded comments now. They’ll do.

      Reply
  21. Ironic. The namespace is correctly declared - even the validator notices it. The namespace attribute isn’t valid HTML, nor are any of the namespaced tags. So, my page is valid XML but invalid XHTML. I can live with that. So long as <xsl:value-of select="document('http://libertini.net/libertus/')//title/text()"/> returns libertus, I’m happy. :)

    I understand the #wordpress addiction! If you prefer e-mail, I’m on that too.

    Reply

Leave a Reply

You may also log in to post a comment.

XHTML:

If you want to <q>tag</q>, please balance these; a, i, em, b, strong, u, blockquote, q, ul, li, ol, abbr, code, pre, sub and sup.