Motivation
Normally topics in a wiki are accessed through links, usually starting from some "home" page. Sometimes it is however useful to (additionally) provide a "linearized" view on some or all of the topics in a web.
The
TocPlugin uses a special WebOrder topic (see example
here) to select topics and their order to create a "Table of Contents" (see example
here), which results in a linearized, ordered presentation of the selected topics.
The suggested TocButtons extension for
TocPlugin allows to add "Prev", "Home" and "Next" navigation buttons (for example, see bottom of page
here) that allow for browsing the topics listed in the WebOrder the way you want to do when reading a book.
When presenting wiki pages like this to users, they will very soon ask for a PDF copy of the whole document, or for a single HTML file of everything (usually they are not even aware about the underlying wiki nature of the document).
In our old (pre-Foswiki) setup we used a hacked version of the PublishPlugin to satisfy such requests (see the HTML file
here or the PDF file
here).
At te moment I'm trying to find a Foswiki based setup to provide the same features as in the examples above. The problem is how to "publish" such a WebOrder based book, i. e. how to create for example the PDF file from it.
Discussion on IRC (see thread starting
here made it clear that such a feature (creating an "ordered" view on a selection of topics) could be interesting for other tasks as well, for example to extract a bibliography etc.
Current status
It seems there are two places where such a feature could be implemented:
- Make it part of the TocPlugin.
Actually TocPlugin already contains code that was probably intended to do exactly this, but it is currently broken. After fixing the obvious problems:
diff --git a/lib/Foswiki/Plugins/TocPlugin/Section.pm b/lib/Foswiki/Plugins/TocPlugin/Section.pm
index b1fd2e0..481474e 100644
--- a/lib/Foswiki/Plugins/TocPlugin/Section.pm
+++ b/lib/Foswiki/Plugins/TocPlugin/Section.pm
@@ -581,8 +581,7 @@ sub toPrint {
my $text = $wif->readTopic($this->wikiName);
# $res .= "Expanding wikiName= " . $wif->webName . "." . $this->wikiName() . " ";
- $res .= TOC::_printWithTOCTags($toc, $wif, $ct, $text);
-
+ $res .= Foswiki::Plugins::TocPlugin::TOC::_printWithTOCTags($toc, $wif, $ct, $text);
}
my $child;
one can create a WebPrint topic (same function and content as WebOrder which then will generate a single HTML page, but still with issues:
- Technically, _printWithTOCTags() is redundant and can be replaced by a call to _processTOCTags(); the code for _printWithTOCTags() can be deleted.
- Optically, the rendering of the HTML page is terrible, with %TABLE tags not substitued, etc. [maybe some templates are missing?]
- Make it part of the PublishPlugin
If I understand the code correctly, in our old version the major hack to PublishPlugin was in publishWeb():
sub publishWeb {
- my ($web, $topic, $wikiName, $inclusions, $exclusions, $skin, $topicsearch, $destZip) = @_;
- # Get list of topics from this web.
- my @topics = TWiki::Func::getTopicList($web);
+ my ($web, $topic, $inclusions, $exclusions) = @_;
- # Choose template.
- my $tmpl = TWiki::Func::readTemplate("view", $skin);
- die "Couldn't find template\n" if(!$tmpl);
+ # Get list of TOC topics from this web.
+
+ $toc = TOC::getToc();
+ $toc->getTopicList(\@topics);
+ #&TWiki::Func::writeDebug("Publish topics: @topics");
Eventually something equivalent could be done. But then, it might be interesting to make the approach more general, for example to allow to use other "order lists" instead of only WebOrder to determine selection and sequence of the topics to process.
--
WolfgangDenk
My main concern here is that we don't create a situation that invites people to re-invent the wheel. As noted there are several scenarios where an ordering of topics is required. An ordering isn't just relevant to one web, but should be able to pick topics from different webs.
One simplae approach is to create a contrib, maybe called something like OrderingContrib. This would support the definition of an ordering using a simple syntax in a topic. For example,
1 FrontisPiece
1 TheBeginning
1 TheMiddle
1 AlternativeEndings.OneEnding
1 AlternativeEndings.AnotherEnding
%SEARCH{"^Appendix" web="Appendices" type="regex" nonoise="on" order="topic" format=" 1 $web.$topic"}%
TheEnd
The ordering is a simple ordered list; hierarchy, if it exists, should be represented by heading levels (though there's perhaps a case for a "heading push" when including a topic to modify the root heading level of an included topic). The list will be macro-expanded (to expand the %SEARCH and any other macros used in it), but the TML ( 1) is a notational convenience to make the topic render nicely in a browser.
OK, so how does this get used? Via an API:
package Foswiki::Contrib::OrderingContrib @isa Foswiki::Iterator
ClassMethod new($web, $topic) -> $iterator
Get a Foswiki iterator over an ordering defined in $web.$topic. The iterator will iterate over the full-qualified and normalised web.topic names for each of the listed topics in turn. For example,
my $it = $ordering->iterator();
while ($it->hasNext()) {
my ($web, $topic) = Foswiki::normalizeWebTopicName(undef, $it->next());
print STDERR "Processing $web.$topic\n";
...
}
The iterator will return all topics in the ordering, even those that do not exist or are inaccessible due to security constraints.
There may be a case for supporting access to the ordering for wiki applications. For example,
%ORDERING{"MyBook" format="..."}%
supporting the standard
header
,
footer
,
separator
,
format
params.
--
CrawfordCurrie - 23 Apr 2010
The more general approach is using
PublishSets. That's what it is called in other CMSes. A publish set is a special topic that defines properties such as
- the name/identifier of the publish set
- the name of the responsible person (not nessarily the list of contributors to the book)
- keywords
- summary
- version
- the state of the publish set such as draft, approved, rejected, ready-to-be-approved, ready-to-be-published, published, unpublished
- kind of publishing process: manual or scheduled automatically
- the date when the set is scheduled to be published
- the date when the set has been published last time
- the date when the set is to be unpublished, that is becoming invalid and will be removed from the publish location, using some archiving means
- the target location where to publish it
- the target location where to unpublish/archive old content
- some other parameters part of the publishing and unpublishing process
- well and the set of documents to be published, either listed explicitly or using some rule matching names or some other search criteria
This all makes up a nice DataForm and a cronjob then searches for all PublishSets ready to be published and does its job.
There are more aspects depending on more specific needs such as type of content, audience, publisher, lisense and copyright.
I'd always add tags and categories as well to let publish sets participate in an overall knowledge management strategy.
So the DataForm definition for PublishSets should be extensible.
There can be any number of publish sets with overlapping sets of topics in there. You'd create a new publish set for each version of the book to be published
or so. Books share common parts appearing
--
MichaelDaum - 23 Apr 2010
+1 for PublishSets, I did something similar with the TocPlugin on my old (tm)wiki - but not as well though out ;-). If a topic was classified as a TocTopic (via a DataForm) it acted as the WebOrder topic for the book, i.e. there could be multiple books per web if there was no WebOrder topic. If a topic was the child of a TocTopic it was given a VIEW_TEMPLATE that had book navigation buttons, back, forward, up. The buttons were courtesy of the NavbarPlugin. I added a tocformat=printview parameter that I used with the GenPDFPlugin when viewing the toc topic to generate a pdf of the book. I also had a printviewforword option that didn't generate the heading numbers so they could be added by Word when the saved page was
File>Insert
'ed.
I also did some hacking to make standard heading syntax, ---[+]+, recognised by the TocPlugin, not just the special %SECTION\d{}% syntax. If a section was to be referenced then a %SECTION{name="whatever"}% had to be added to the heading line.
Also, the TOCIF stuff should probably be extracated from the plugin and just use the Func API.
--
DavidPatterson - 23 Apr 2010
It would be interesting if one could define a
META:FIELD
name to use as a linked list ("next" type relationships). Although not for publishing, I've been experimenting with topics that have arbitrary graph relationships, it's proved quite useful. Linked lists aren't Enough though. You'd need another field like
TOPICPARENT
to indicate hierarchy
--
PaulHarvey - 23 Apr 2010
Using TOPICPARENT has got a list of sever drawbacks that mostly render it useless for real categorization:
- nodes in the hierarchy are containers for content as well; there's no distinction between taxonomy and content being categorized
- this also renders TOPICPARENT fragile to encode a hierarchy
- people adding content aren't taxonomy experts at the same time
- this only allow constructing very simpistic taxonomies: only one parernt, no cycles, only one facet, one topic is only categorized within one taxonomy
Using
JQueryPlugin we've got a list editor with autocompletion, textlistbox, see the
JQueryAjaxHelper how to add autocompletion of topics.
--
MichaelDaum - 23 Apr 2010
Let's get back on track here; Michael and I are talking about the same thing, what he calls PublishSets. My simplistic UI could be extended to take account of the meta-information about the publish set, or we could simple define a form type in the OrderingContrib (OK, call it the PublishSetContrib, whatever) and use Foswiki field data instead.
--
CrawfordCurrie - 23 Apr 2010
Yes, this is another usecase for what I was calling
ResultSets - though clearly the name is sub-optimal.
Additionally, it would be better to not limit the 'set' to topics - rather to make it a
named, ordered list of TOM-addressable items. using a linked list type relationship doesn't really give us the power that a user might what - there's nothing that suggests that an element can't be repeated..
for eg
%RESULTSET{"full_documentation" list="TopicOne, SeparatorTopic[sectionname], TopicTwo, SeparatorTopic[othersectionname], TopicThree"}%
%!FOREACH{"$resultset(full_documentation)" format="$text"}%
might be able to allow custom tweaking of separators, where the simpler case would be something like
%RESULTSET{"full_documentation" list="TopicOne, TopicTwo, TopicThree"}%
%!FOREACH{"$resultset(full_documentation)" format="$text" separator="$query(SeparatorTopic[sectionname])"}%
(or will we have @QUERY(SeparatorTopic[sectionname])@ in foswiki 2.0 :) )
similarly, the named resultset would be accessible via
Foswiki::Func
ok, yes, I've taken the liberty to pretend that
SeparatorTopic[sectionname]
could be used to identify a named section in a topic - we still need to work out a syntax for it.
and no, the
RESULTSET
syntax is not great, nor final, I'm only using it to give an example of
one way we could do it.
please, don't get hung up about the specifics of the syntax I use in the example - I'm illustrating the concept.
--
SvenDowideit - 23 Apr 2010
OK, that's good, I think we have agreement in principle and the main points:
- Publish sets are sets of topics with additional meta-data (which may be defined using a data form)
- Publish sets may be compiled from result sets
- When defining publish sets, we must be careful not to preclude addressing items at finer levels of detail (TOM addressing), even if it isn't supported at first.
I think all these points can be accommodated. Anything else?
--
CrawfordCurrie - 24 Apr 2010