create new tag
, view all tags

RecursiveRenderPluginDev Discussion: Page for developer collaboration, enhancement requests, patches and improved versions on RecursiveRenderPlugin contributed by the TWikiCommunity.
• Please let us know what you think of this extension.
• For support, check the existing questions, or ask a new support question in the Support web!
• Please report bugs below

Development discussion for RecursiveRenderPlugin

Leave feedback here.

-- WalterMundt - 20 Jan 2003

Great feature, Walter, thanks for packaging it!

Perl 5.6.1, ok. Can someone test with 5.005_03 as noted on TWiki.TWikiSystemRequirements?

-- GrantBow - 23 Jan 2003

Hello Walter,

sorry for being a dummy, but what is this plugin helpful with?


As it is, this is mainly useful for doing interesting/arbitrary formatting within a table, ie having tables-within-tables. It could also be used with complex FormattedSearch setups, to create tabular output. -- WalterMundt - 04 Feb 2003

-- MartinRaabe - 04 Feb 2003

Request for a later feature: Render the code, and also cache it (i.e. save it) as part of topic. So the directive takes 3 args: 1. Configuration info that decides whether to render, or to use cache (such as expiry-time reached, the Included File's version changed etc.) 2. The code to render 3. The rendered HTML or twiki markup code. (The third part could run into lines and lines, and it should itself not contain another render statement.)

Whether the cache should be part of topic, or attached to topic as another file, I am not sure. It could even integrate with CachePlugin.

Some of the use cases:

  • I would like to INCLUDE some important web pages, which will be available even when connectivity is lost, or as part of notified email.
  • It will be possible for us to reduce the overhead in using a skin such as Flexible skin. You create a single template file out of all INCLUDEd parts of all templates, and use it during the view. The view will read one template file, and one topic file. So no. of file reads can dramatically decrease.

-- VinodKulkarni - 04 Feb 2003

Definitely an idea, but one that would be rather complex to implement, especially the part about storing the rendered result in the topic...not sure how that'd be accomplished...

-- WalterMundt - 04 Feb 2003

I agree. To me, 'Render' concept seems to be an important one that solves many problems. I am just trying to put some thoughts here for clarity:

Main idea behind Render plugin is that it associates a piece of text (not necessarily twiki-marked) with a name. Using it as macro is first practical use of this. But, there are more:

  • In theory, it is addressable 'logical' entity. Like topics have URL, the rendered entities can have URLs too. This is different from hierarchical web because these are logical entities, where the hierarchy can be made independent of underlying file and directory structure. I could, in theory, define multiple tree views on same set of information.
  • The concept allows variety of activities on only parts of topic:
    • Edit only part of long topic. (See SectionalEditPlugin, the concept can be same).
    • The renderable entity can have a type (such as list or table). This will in turn allow us to create edit controls based on structures.
    • We could associate a specific style with rendered entity. (Very easy using div's.)
    • The rendered entity allows you to control the dynamicity in the page. (This is the example I gave earlier.) We could associate a cache. Idealy as part of page itself.
    • We can associate the rendered entity with a database or other stores. For example, I could format the data within rendered entity using YAML or XML. And for on-screen show (with appropriate style), I could use appropriate table (or tree, or list etc.) rendering. See my comments (and a prototype plugin) in TemplateToolkit
    • I am specifically interested in creating a mechanism that associates a twiki table with a Database table. (And 'click to synchronize' capability to make sure that both are in sync.) By associating a topic + rendered entity with database table, and by reducing any other overhead of managing a table, twiki becomes a very good integration mechanism for organizational information.

In all, I find this a very important abstraction to let us evolve twiki towards management of structured data as well.

-- VinodKulkarni - 09 Feb 2003

Hrmm...interesting indeed. When I first came up with this plugin, I was thinking only to get around certain constraints in the TWiki rendering methodology; you've found a lot of potential that I neven even thought of.

One thing you may want to be aware of is the DatabasePlugin, which allows you to pull data in a read-only fashion out of a database and display it in TWiki. This could potentially be extended with edit functionality.

I'm thinking about how to represent some of your ideas syntactically. I'm thinking that the most consistent way to do this would be to give the <render> plugin attributes. For example, a <render name="foo" visible="no"> blah </render> block would be equivalent to a ~foo macro. This would allow you to introduce things like:

  • method: Allow other methods of rendering content than passing it through the TWiki rendering engine. Examples:
    • XSLT: apply an XSL sheet to XML contents to generate (X)HTML
    • list: Automatically listifies the contents, perhaps word-by-word; allows for compact lists of things to be presented neatly.
    • verbatim: equivalent to the current <verbatim> tag.
  • source: Allow for other sources of data, i.e. have an empty <render ... /> tag that pulls its contents
  • style: As you mentioned, to allow wrapping the contents in a div or span tag and provide CSS style info.
  • editable: for methods (incl. the default) that are by nature editable, where the data is stored in the topic, specifies whether to add edit controls. (something like SectionalEditPlugin's for default, other things for other methods).

As you can see, nearly all of the concepts you laid out could be expressed this way.

Whether anyone will actually add these capabilities to the plugin is another story entirely - many of them would require a significant restructuring of the plugin.

We shall see.

-- WalterMundt - 09 Feb 2003

I added the SHORTDESCRIPTION setting. Best to include that in the next Plugin release.

-- PeterThoeny - 19 Jul 2003

Because this plugin is used and maintained I have given it a non-default CVS modification policy. If you have a problem with this, switch it back.

-- CrawfordCurrie - 03 Apr 2004

Observation 1: The ~ syntax is sensitive to the difference between newlines and linefeeds. Watch out if you work on a PC and use cygwin.

Observation 2: The =<render> syntax is very sensitive to correctly balanced tags. Code should be made more resilient to user error.

-- ThomasWeigert - 02 Mar 2005

I'm successfully using this Plugin with DEVELOP but am considered about its performance impacts. Any experiences with this around?

-- FranzJosefSilli - 01 Apr 2005

I would prefer to change the way it fetches the ~macro tag: instead of \n use ^, so one can put a macro definition in the very first line as well.

--- R   2003-01-21 22:54:00.000000000 +0100
+++ RecursiveRenderPlugin.pm    2006-01-16 11:10:01.486648500 +0100
@@ -114,7 +114,7 @@
     # This handler is called by getRenderedVersion just before the line loop

     # read in ~macros
-    while ($_[0] =~ s/\n~([^\n]*)\n(.*?)\n~~(?=\n)//s) {
+    while ($_[0] =~ s/^~([^\n]*)\n(.*?)\n~~(?=\n)//s) {
         my $macroName = $1;
         my $macroText = TWiki::Func::renderText($2, $_[1], $_[2]);
        $macroText =~ s/~(?=$macroName)/~<nop>/g; # no direct recursion

-- AndrasSzell - 16 Jan 2006

I am running into a problem. If I user the render tag in a cell in a table it works fine. However if I change this table to an EDITTABLE then it does not work correctly. The heading gets associated with the edit table and the body gets put into a separate table. If I change leave the render tags but remove the search, it works correctly. The search returns multiple hits and the format it returns is the topic name of the pages it finds.

-- RickMach - 31 Jan 2006

I just ran into a problem with unbalanced tags and the RecursiveRenderPlugin. Somebody alerted me to a page she couldn't open. I looked and sure enough, I couldn't see the page. I looked at the .txt file on the server and it seemed unobjectionable. I tried feeding the page to the view script in the debugger and after a bit of fumbling about saw a vast string of error warnings all alike:

view: Use of uninitialized value in substitution (s///) at /usr/lib/cgi-bin/lib/TWiki/Plugins/RecursiveRenderPlugin.pm line 168.
I went and looked up the plugin syntax and then examined the .txt file again, determining that the author had begun a <render> block which she never ended. I edited the file by hand, adding the closing tag back in, and the problem went away.

So, it looks like the plugin currently doesn't recover from unbalanced tags. I'm going to see about at least killing the code when it loops more than some number of times but a more graceful result would surely be superior.

-- DavidHoughton - 02 Apr 2008

Alright, here's a patch that fixes the problem above well enough. If it finds an unbalanced <render> it converts this to &lt;render&gt;.

==== Patch <unbalancedTags> level 1
Source: [No source]
Target: 8f3e6c68-2be0-46b6-b1c9-40c738eef9e6:/cgi-bin/lib/TWiki/Plugins:456 [local]
fixed plugin so it doesn't die with unbalanced tags
=== RecursiveRenderPlugin.pm
--- RecursiveRenderPlugin.pm    (revision 456)
+++ RecursiveRenderPlugin.pm    (patch unbalancedTags level 1)
@@ -162,16 +162,20 @@
     my $newText = $_[0];
     my $idx = rindex($newText, "<$tag>");
     while ($idx != -1) {
-       my $endText = substr($newText, $idx);
-       $endText =~ s!<$tag>(.*?)</$tag>!$prefix$renderCount!is;
-       my $toRender = $1;
-       $toRender =~ s/$prefix/$rprefix/;
-       my $rText = TWiki::Func::renderText($toRender, $_[1], $_[2]);
-       $rText =~ s/$rprefix/$prefix/;
-       $$renderedText[$renderCount] = $rText;
-       $renderCount++;
-       $newText = substr($newText, 0, $idx) . $endText;
-       $idx = rindex($newText, "<$tag>");
+           my $endText = substr($newText, $idx);
+           if (index($endText, "</$tag>") > -1) {
+                   $endText =~ s!<$tag>(.*?)</$tag>!$prefix$renderCount!is;
+                   my $toRender = $1;
+                   $toRender =~ s/$prefix/$rprefix/;
+                   my $rText = TWiki::Func::renderText($toRender, $_[1], $_[2]);
+                   $rText =~ s/$rprefix/$prefix/;
+                   $$renderedText[$renderCount] = $rText;
+                   $renderCount++;
+           } else {
+                   $endText = '&lt;'.$tag.'&gt;'.substr($endText, length "<$tag>");
+           }
+           $newText = substr($newText, 0, $idx) . $endText;
+           $idx = rindex($newText, "<$tag>");
     $_[0] = $newText;
I didn't perltidy this so it's still perlmessy. (I didn't want to confuse the diff algorithm.) The crucial bits are these:
           if (index($endText, "</$tag>") > -1) {
           } else {
                   $endText = '&lt;'.$tag.'&gt;'.substr($endText, length "<$tag>");
The first bit checks to see whether there's any closing tag. The second bit hides the unbalanced tag when necessary.

-- DavidHoughton - 02 Apr 2008

Edit | Attach | Watch | Print version | History: r21 < r20 < r19 < r18 < r17 | Backlinks | Raw View | Raw edit | More topic actions
Topic revision: r21 - 2008-04-02 - DavidHoughton
  • Learn about TWiki  
  • Download TWiki
This site is powered by the TWiki collaboration platform Powered by Perl Hosted by OICcam.com Ideas, requests, problems regarding TWiki? Send feedback. Ask community in the support forum.
Copyright © 1999-2018 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.