TiddlyTemplating

32 views
Skip to first unread message

JayFresh - http://jayfresh.wordpress.com

unread,
Jan 23, 2008, 3:59:57 PM1/23/08
to TiddlyWikiDev
This is for anyone with an interest in TiddlyWiki's ability to create
other files...

Been thinking a lot about using TiddlyWiki as a blogging platform, or
as a content-management system for websites.

The <a href="http://www.superphysique.net/#%5B%5BSEO%20TiddlyWiki
%20Plugin%5D%5D">SEOTiddlyWikiPlugin</a> does a really nice job of
saving files from the tiddlers. However, to control what you end up
creating, the first thing that comes to mind is templating.

There are a few Javascript templating engines out there. But
TiddlyWiki comes with a huge templating engine built right into the
middle - the wikifier! This is the guts that takes wikitext and pumps
it out as html (or indeed whatever the chosen formatter tells it to).
So if we have a template written in wikitext, and we use macros to
fill in content (such as the "view macro", which is the method used in
tiddler templates), then with a little tweaking to make sure the right
data is accessible at the right time, we've got ourselves a basic
TiddlyTemplating prototype.

Check it out, creating an RSS feed, <a href="http://
jonny.jonathan.googlepages.com/TiddlyTemplating.html">here</a>. The
source is in <a href="http://svn.tiddlywiki.org/Trunk/contributors/
JonathanLister/verticals/TiddlyTemplating/">subversion</a> (you'll
want <a href="http://trac.tiddlywiki.org/wiki/Cook">Cook</a> to
compile - the docs for this are very thin on the ground, get in touch
if you need a hand with this).

See if you think the syntax for the templating makes sense. I've
attempted to keep the presentation logic entirely away from the
application logic, so that someone messing with the template can't
break the application.

This ALMOST works...


J.

JayFresh - http://jayfresh.wordpress.com

unread,
Jan 24, 2008, 1:17:14 PM1/24/08
to TiddlyWikiDev
Hello,

After going through a few options, I've come up with one that works.
This TiddlyTemplating prototype works, in that it generates a RSS feed
from templates on the fly - you can even go in and edit the templates.

http://jonny.jonathan.googlepages.com/TiddlyTemplating.html

It's still a prototype so it has some rough edges, but the basic
puzzle to solve was how to get a templating syntax and processor that
allowed you to work with either a bunch of tiddlers or some data
belonging to one of those tiddlers.

Source:
ListTemplateMacro.js - http://svn.tiddlywiki.org/Trunk/contributors/JonathanLister/components/ListTemplateMacro.js
Bits and pieces for the example TiddlyWiki -
http://svn.tiddlywiki.org/Trunk/contributors/JonathanLister/verticals/TiddlyTemplating/


J.

On Jan 23, 8:59 pm, "JayFresh - http://jayfresh.wordpress.com"

Eric Shulman

unread,
Jan 24, 2008, 1:53:35 PM1/24/08
to TiddlyWikiDev
> ListTemplateMacro.js -http://svn.tiddlywiki.org/Trunk/contributors/JonathanLister/component...

Your code redefines the config.macros.view.handler() function... as
currently written, this code "steps on" any other plugins that also
make changes to the <<view>> macro handler.

You should try to avoid *overwriting* core functions unless absolutely
necessary. Instead, whenever possible, you should *hijack* those
functions, adding your functionality either before or after invoking
the hijacked code (via the "apply(this,arguments)" method). This
allows other plugins that also hijack these functions to continue to
operate.

Of course, hijacking the function is not always possible, given the
nature of the specific core function, or the changes you want to
make. In that case, it is important to clearly note in your plugin
documentation that installing this plugin may have adverse affects on
other plugins installed in the same document.

-e


Eric Shulman

unread,
Jan 24, 2008, 2:03:05 PM1/24/08
to TiddlyWikiDev
> ListTemplateMacro.js -http://svn.tiddlywiki.org/Trunk/contributors/JonathanLister/component...

Your code is defining a macro: <<now what format>>

Except perhaps for the "GMT" option, why is this macro needed? You
can get the current date/time, formatted however you want, using:
<<today format>>
including "<<today hh>>" and "<<today YYYY>>", which will produce the
same results as your <<now hh>> and <<now YYYY>> macro calls.

By using the core's built-in <<today>> macro, you could then simplify
your code to just define "<<gmt>>", like this:

config.macros.gmt = {
handler:
function(place,macroName,params,wikifier,paramString,tiddler) {
createTiddlyText(place,new Date().toUTCString());
}
};

HTH,
-e
Eric Shulman
TiddlyTools / ELS Design Studios
Message has been deleted

Eric Shulman

unread,
Jan 24, 2008, 6:21:11 PM1/24/08
to TiddlyWikiDev
> ListTemplateMacro.js -http://svn.tiddlywiki.org/Trunk/contributors/JonathanLister/component...

After studying your example RSSTemplate, it seems that the main reason
that you tweaked the core <<view>> macro was so you can reference TW
internal variables (e.g., version.*) instead of the usual tiddler
fields.

However, rather than altering the core view macro, you might want to
consider using the <<wikify>> macro:
http://www.TiddlyTools.com/#WikifyPlugin
The macro uses the core's string-substitution mechanism to let you
assemble and format output from a mix of values contained in tiddler
fields, tiddler slices, and/or internal TW variables.

Thus, instead of writing:
<<view version.major text global>>.<<view version.minor text
global>>.<<view version.revision text global>>

you could write:
<<wikify "%0.%1.%2" {{version.major}} {{version.minor}}
{{version.revision}}>>

Of course, this is just one example of how <<wikify>> can be used to
render formatted content. I imagine that there could be numerous uses
for <<wikify>> in generating all sorts of output as part of your
"TiddlyTemplating" process.

Ken Girard

unread,
Jan 24, 2008, 10:55:54 PM1/24/08
to TiddlyWikiDev
"<<wikify "%0.%1.%2" {{version.major}} {{version.minor}}
{{version.revision}}>>"

So that is how that works.
I've known it existed, but could never wrap my head around it till I
read that.

Thanks,
Ken Girard

Saq Imtiaz

unread,
Jan 25, 2008, 3:00:48 AM1/25/08
to Tiddly...@googlegroups.com
First off: I think template based saving is a terrific idea and I am very happy to see you taking a crack at it. Properly done this could open up a whole world of interesting applications for TiddlyWiki.

As for your code: It is my understanding that this is proof of concept only, so personally I don't see any real need at this time to critique the way it has been implemented at the code level. We can do that a little later in the game as I am expecting that your code will change drastically in the days to come anyway.

What I will point out however, is that I'm not entirely happy with the way the templates look. The use of the ListTemplate macro and the parameters it uses makes writing a template akin to writing code almost, and probably a little too complex for the casual user to follow. I would really like to see a more intuitive syntax.

TiddlyWiki already does recursive templates, you can include a template in another template using [[subtemplate]].
The problem in this case is that a template might need to be applied to more than one tiddler, so perhaps the intuitive thing to do might be to extend the normal syntax for including a subtemplate to handle that situation?

Another alternative could be something similar to cook recipe files, to specify the different templates and how they are put together.

I don't really have an ideal alternative at this time but I would love to see a syntax that easily translates into English as meaning:

'This is my header, then take these tiddlers and apply this template to them, add a footnote, then add my footer from this template.'

Cheers,
Saq
--
Tiddly Learning ( http://lewcid.org ) : TiddlyWiki news, plugins, themes and educational usage

JayFresh - http://jayfresh.wordpress.com

unread,
Jan 25, 2008, 6:55:42 AM1/25/08
to TiddlyWikiDev
Saq,

Great feedback. Can you suggest a syntax that would be simpler?


J.
> >http://svn.tiddlywiki.org/Trunk/contributors/JonathanLister/component...
> > Bits and pieces for the example TiddlyWiki -
>
> >http://svn.tiddlywiki.org/Trunk/contributors/JonathanLister/verticals...
>
> > J.
>
> > On Jan 23, 8:59 pm, "JayFresh -http://jayfresh.wordpress.com"
> Tiddly Learning (http://lewcid.org) : TiddlyWiki news, plugins, themes and
> educational usage

JayFresh - http://jayfresh.wordpress.com

unread,
Jan 25, 2008, 7:04:30 AM1/25/08
to TiddlyWikiDev
Eric,

Thanks very much for the response! I'll go through what you've
suggested:

Hijack vs. overwrite for view macro - I completely agree and this is
bad practice on my part.

Now macro - I didn't realise there was a built-in today macro, thank
you for pointing that out. You suggested writing another macro for the
GMT case, but what do you think about just extending the today macro?

Referencing global variables with the view macro - I've been pointed
towards the core message macro lets you access config.* variables. The
idea would be to generalise that plugin so you can access any of the
globals. Does that make sense to you?



J.

Saq Imtiaz

unread,
Jan 25, 2008, 7:47:16 AM1/25/08
to Tiddly...@googlegroups.com
Sadly Jon I haven't been able to come up with a good alternative, but that is not to say that it cannot be done.

Wondering if we could use something like [tag[rss]] [[InnerTemplate]]  ?
 
Am also wondering if we could borrow some techniques from the way PageTemplates work. That is, <node tiddler='SiteTitle'></node> instead of using <node><<tiddler SiteTitle>></node>

Haven't thought through all the pros and cons but it might be worth a thought.

Cheers,
Saq

PS: The way TW usually does templates is to first fetch the entire template recursively using store.getRecursiveTiddlerText () and then applying htmlMacros. Wonder if something similar could be done here to simplifying the way templates are rendered.

>
> > J.
>
> > On Jan 23, 8:59 pm, "JayFresh - http://jayfresh.wordpress.com"



--
Tiddly Learning ( http://lewcid.org ) : TiddlyWiki news, plugins, themes and educational usage

FND

unread,
Jan 25, 2008, 10:37:29 AM1/25/08
to Tiddly...@googlegroups.com
I tend to agree with Saq usability concerns.

> Wondering if we could use something like [tag[rss]] [[InnerTemplate]] ?
> Am also wondering if we could borrow some techniques from the way
> PageTemplates work. That is, <node tiddler='SiteTitle'></node> instead
> of using <node><<tiddler SiteTitle>></node>

I guess the using the new filter technique is a must.
But I don't quite like the use of attributes for this.
How about something that resembles {{evaluated parameters}} - this
obviously isn't well thought through yet, but it might be an option.

What kinda irritates me is that these templates are different from the
default ones (Page- and ViewTemplate). That is not to say the current
way of embedding macros (an extra HTML element with a macro attribute)
is perfect, but I think overall consistency is important.


-- F.

Eric Shulman

unread,
Jan 25, 2008, 11:47:03 AM1/25/08
to TiddlyWikiDev
> Referencing global variables with the view macro - I've been pointed
> towards the core message macro lets you access config.* variables. The
> idea would be to generalise that plugin so you can access any of the
> globals. Does that make sense to you?

That's exactly why I wrote WikifyPlugin... to generalize the ability
to output formatted content contructed from internal values. Unless
your changes are going to be merged into a future core release, I see
no added value in re-defining the core's <<message>> macro when
WikifyPlugin already provides this functionality (and more) in a very
robust fashion. There's no need to "reinvent the wheel"...

-e

Eric Shulman

unread,
Jan 25, 2008, 12:04:18 PM1/25/08
to TiddlyWikiDev

> As for your code: It is my understanding that this is proof of concept only,
> so personally I don't see any real need at this time to critique the way it
> has been implemented at the code level.

Whether "proof-of-concept" or "final release", it is never too early
to start practicing good TiddlyWiki programming habits. While my
feedback identified specific instances, it was intended to illustrate
some fundamental issues that apply to ALL plugin development:

* Hijacking vs. replacing a core function (i.e., working well with
other plugins, future-proofing against core updates, and making
minimal changes, only as necessary)

* Know about and reuse existing functionality whenever possible (this
applies to use of existing plugins as well as core functions)

-e



Saq Imtiaz

unread,
Jan 25, 2008, 12:08:31 PM1/25/08
to Tiddly...@googlegroups.com
Actually Eric, my comment there had nothing to do with your feedback. It was an explanation for why I wasn't going to get into those details in my own feedback. Jon and I had already spent a good hour on that already just a little earlier.

 Cheers, Saq

JayFresh - http://jayfresh.wordpress.com

unread,
Jan 25, 2008, 12:09:49 PM1/25/08
to TiddlyWikiDev
I think you're both on to something there.

1) I like the concept of using store.getRecursiveTiddlerText() to
"unfold" the templates before running the macro parser over them. The
way it works at the moment is that the recursive function is the
entire ListTemplate macro, and that unfolds the template and executes
the macros all at the same time. Clearly the core TW template parser
hands over the whole recursive thing to the getRecursiveTiddlyText
function - I don't know which is better, but I recognise the need for
consistency. Would be good if we could even use the core template
parser to do it all.

The nature of the templates themselves would have to have to change if
we used the core templater - ViewTemplate and the rest are HTML
templates that are just inserted as innerHTML and the div attributes
contain the macro calls. The TiddlyTemplating templates are wikitext,
which is wikified. Big difference?

2) [tag[rss]] [[InnerTemplate]] - is it simpler than <<ListTemplate
filter:"[tag[rss]]" template:"InnerTemplate">> ? With the latter you
have words explaining the arguments.


J.

JayFresh - http://jayfresh.wordpress.com

unread,
Jan 25, 2008, 12:12:49 PM1/25/08
to TiddlyWikiDev

> That's exactly why I wrote WikifyPlugin... to generalize the ability
> to output formatted content contructed from internal values. Unless
> your changes are going to be merged into a future core release, I see
> no added value in re-defining the core's <<message>> macro when
> WikifyPlugin already provides this functionality (and more) in a very
> robust fashion. There's no need to "reinvent the wheel"...

I'm all for not reinventing the wheel, and in this specific instance I
have seen an opportunity to generalise a core function, which was
clearly written for something more specific. I do intend to submit the
change as a core mod.


J.

Saq Imtiaz

unread,
Jan 25, 2008, 12:13:57 PM1/25/08
to Tiddly...@googlegroups.com
With regards to #1 you are correct that you might need to change the templates quite a bit. The concern with first expanding the templates is that somehow you have to remember which parts of the template refer to which tiddler.... so that needs some thought.

About #2, as I mentioned before, I'm not too happy with that syntax either. What I'm trying to get at is that it might be preferrable to have some derivative of the existing inclusion mechanisms and syntax for templates.... right now for a single include we just do [[InnerTemplate]]. Using a macro for this just leaves a bad taste in my mouth. It might just be a case of personal preferences, but it just does not sit right with me.

Cheers,
Saq

Paul Downey

unread,
Jan 25, 2008, 6:25:46 PM1/25/08
to Tiddly...@googlegroups.com

On 24 Jan 2008, at 18:53, Eric Shulman wrote:

> You should try to avoid *overwriting* core functions unless absolutely
> necessary. Instead, whenever possible, you should *hijack* those
> functions, adding your functionality either before or after invoking
> the hijacked code (via the "apply(this,arguments)" method). This
> allows other plugins that also hijack these functions to continue to
> operate.
>
> Of course, hijacking the function is not always possible, given the
> nature of the specific core function, or the changes you want to
> make. In that case, it is important to clearly note in your plugin
> documentation that installing this plugin may have adverse affects on
> other plugins installed in the same document.

Great advice, I've shoved it onto the Wiki:

http://www.tiddlywiki.org/wiki/Dev:Best_Practices

Paul (psd)
--
http://blog.whatfettle.com

JayFresh - http://jayfresh.wordpress.com

unread,
Jan 28, 2008, 7:52:47 AM1/28/08
to TiddlyWikiDev
Hello.

I've fleshed out the TiddlyTemplating examples a little with two more
(see all at http://tinyurl.com/yt9nh4):

- standard RSS saving overridden: when you save the RSS feed, it uses
TiddlyTemplating instead of the built-in mechanism. Caveat: because
there is no [tag[!excludeLists]] filter syntax yet, this is using
[tag[docs]] just to pop a couple of tiddlers into the output

- saving HTML files: I mocked up a copy of my blog homepage using a
two templates and a couple of test tiddlers as posts. There are some
ends to tie up (such as linking to pages for each post!), but you can
see the result at: http://tinyurl.com/23fqu7



J.

Jack

unread,
Jan 28, 2008, 9:57:05 AM1/28/08
to TiddlyWikiDev
J.
I was looking for a way to manage tiddlers in external XML files and
was referred to your ListTemplateMacro. As I understand it, it lists
tiddlers and then, combined with the HtmlPageTemplate could be used
for generating external sites. While I'm not sure I will be able to
use all of what you've done, I noticed a striking parallel with my
TiddlerListMacro and my PublishMacro. Take a look at these in case
you're re-inventing the wheel ;-) - as far as I can see we're doing
the same thing.
Cheers
Jack

http://jackparke.googlepages.com/jtw.html

On Jan 23, 9:59 pm, "JayFresh - http://jayfresh.wordpress.com"

Jack

unread,
Jan 28, 2008, 10:08:01 AM1/28/08
to TiddlyWikiDev
I've found beginners are be fine with things like:
<<tiddlerList tags:"People,-Enemies" order:"-created">
Where "-" means exclude and the comma logic is AND
and you can do complex expressions for advanced users:
<<tiddlerList filter:"created.format('YYYY')=='2007'">

On Jan 25, 12:55 pm, "JayFresh - http://jayfresh.wordpress.com"
> > educational usage- Hide quoted text -
>
> - Show quoted text -

JayFresh - http://jayfresh.wordpress.com

unread,
Jan 28, 2008, 10:45:43 AM1/28/08
to TiddlyWikiDev
Hi Jack,

Thanks for the pointers and the comments. I'd love to be able to help
you out with your use case (pretty exciting to have my plugin referred
to someone), but I don't entirely understand what you mean by "manage
tiddlers in external XML files" - could you elaborate? It sounds like
you want to store tiddlers *in* external XML files.

I had a look at your PublishMacro when I was looking into how to do
template-based saving, and it helped me think about what the flow
should be. I'd like to know your logic behind your templating system -
it looks like it uses the format method to "fill in" the templates,
but I think that locks the meaning of %1, %2, etc. to this particular
implementation of the plugin; I have attempted to separate the
template syntax from the code that processes them, hence lots of use
of common macros like the view macro.

I appreciated your tip about a suggested macro syntax that is easy for
beginners to understand but flexible enough for advanced use. This is
one area in particular that has caused a lot of discussion (check into
#tiddlywiki on irc.freenode.net and you'll see what I mean).



J.

On Jan 28, 3:08 pm, Jack <cawo...@gmail.com> wrote:
> I've found beginners are be fine with things like:
> <<tiddlerList tags:"People,-Enemies" order:"-created">
> Where "-" means exclude and the comma logic is AND
> and you can do complex expressions for advanced users:
> <<tiddlerList filter:"created.format('YYYY')=='2007'">
>
> On Jan 25, 12:55 pm, "JayFresh -http://jayfresh.wordpress.com"
Reply all
Reply to author
Forward
0 new messages