Mark up overlapping list items

Edit (forgot to start with an overview of the question): Is there a sensible way to use the <$list /> widget that would allow me to start a element (<p>) inside one item and close it (</p>) inside a subsequent one?

In a recent thread (King James Bible Wiki), I describe a new experiment. Creating the tiddlers worked as hoped; most everything else went well. But I’m really unhappy with the technique of one of my templates.

$:/_/bible/templates/chapter is a simple-enough ViewTemplate, checking if the tiddler has the correct tag, calling the procedure $:/_/bible/procedures/chapter, and then wikifying the results.

That feels ridiculous. That procedure generates text like this:

^^[[1|Genesis 1:1]]^^ In the beginning God created the heaven and the
earth. ^^[[2|Genesis 1:2]]^^ And the earth was without form, and void; 
and darkness //was// upon the face of the deep. And the Spirit of God
moved upon the face of the waters. 

^^[[3|Genesis 1:3]]^^ And God said, Let there be light: and there was
light. ^^[[4|Genesis 1:4]]^^ And God saw the light, that //it was// good: 
and God divided the light from the darkness. ^^[[5|Genesis 1:5]]^^ 
And God called the light Day, and the darkness he called Night. And t
he evening and the morning were the first day. 

(line breaks added for readability.)

and then I pass the result to wikify,

This all works, but I feel I should have been able to generate the output HTML/DOM directly and not needed to wikify. I usually can do so, but there was a problem here: The output markup needed to span list items. My basic tiddlers are the verses. To create a chapter, I need to combine them. That’s easy enough to do with a <$list /> of course. If I wanted each verse to start on its own line, this would be trivial, as it would be if I wanted them all run together. But I want something in between.

Each verse has an field new-para which reports whether it’s the start of a new paragraph. In the sample above verses 1 and 3 are “yes”, verses (do you know how hard it is not to type “versus”?) are “no”. So 1 and 2 should be wrapped in their own <p> tag and verses 3. 4. and 5 in another one. (There should probably be an exception for—at least—Psalms, but I haven’t thought that through yet.)

I can do this sort of control-break logic easily enough—if wordily— in TW, but it seems that a widget like <$list /> wants to generate complete DOM nodes. It’s not acceptable that <p> is output in one list item and the corresponding </p> is in a later one. (If that’s not the case, please let me know; perhaps I was misinterpreting the symptoms.)

But if I’m generating plain text, it doesn’t care. So I can add my <p>, <sup>, and <i> and their closing partners wherever it makes sense. So I do so and then wikify the results. And since its slightly easier, I use blank lines ^^ and // instead of their HTML counterparts. But I don’t want to be doing this at all, and I’m wondering if anyone can offer suggestions.


I do have one possibility that I’ve mostly discarded, but maybe someone can suggest a good reason to recycle it: I could add another layer to my tiddler hierarchy to cover paragraphs. If I had tiddlers tagged Paragraph nested inside each Chapter and had the Verses inside those, this would be almost trivial, just one more layer of nested lists. But that feels really wrong. The data should contain Books, Chapters, and Verses, and nothing else. If would feel like the tail wagging the dog.


And as I wrote up that last bit, I thought of a reasonable compromise. I should be able to replace my new-para: yes/no with a simple para with the paragraph number. That should let me create my list directly. I will go try that. But that only works because I have great control over the structure of my data. I would still like to know if there’s a good way to create lists where an HTML element starts in one list item and finishes in another – a way that doesn’t involve wikifying my text output. Any suggestions?

I know, that’s not what you did ask for, but it was the first thing that jumped into my eyes when I saw the code.

Your numbering of the verses seems to rely on the list-counter, which imo is not optimal. If I only want to render verse 3-5, which belong together with a different filter They will be listed as 1-3 which is wrong.

Your verse-fields do have the real data. IMO you should use that instead.


Thinking about the paragraphs in 1 chapter, I would probably experiment with a recursive procedure, instead of a list and the wikify widget.

I would probably make the verse-number-link it’s own procedure, just to get it out of the way in the main code.

just some thoughts.
-m

My spontaneous guess is “no” because each item output from a listwidget is wrapped in a div (or a span if not on new lines) and you cant do <div><p></div>...<div></p></div>.

However, you can probably post-mangle stuff visually with css. One idea might be to wrap each nested listwidget in a div with some class that you thereafter manipulate… display:block/inline-block/inline… even span {display:table} for injecting a linebreak for a span.

I’ve previously made liststyles to showcase some ways to manipulate listwidget output that might give some futher ideas. Or not.

Been there, done (hopefully) that.

You aint gonna like this but…

I used &nbsp; <br> and <br><br> keyed on SP, BR, and BRBR ← added to the source text.

I know, I know, you can’t add those to the entire text of the bible.

So, is there anything in the text that “clues you in”? You know, search-replace? (or “live”, inplace replacements).

This did work. I added paragraph numbers to Verse tiddlers in place of the new-para boolean field. I now have a reasonable-looking template for Chapters:

<% if [<currentTiddler>tag[Chapter]] %>
<div class="chapter">
<$let book={{{ [<currentTiddler>get[book]] }}} chapter={{{ [<currentTiddler>get[chapter]] }}} >
<$list filter="[tag[Verse]] :filter[book<book>] :filter[chapter<chapter>] :map[get[para]] +[unique[]] +[nsort[]]" variable="para">
<p>
  <$list filter="[tag[Verse]] :filter[book<book>] :filter[chapter<chapter>] :filter[para<para>] +[nsort[seq]]">
    <span class="verse">
      <sup class="verse-number"><$link>{{!!verse}}</$link></sup>
      <span class="text">{{!!text}}</span>
    </span>
  </$list>
</p>
</$list>
</$let>
</div>
<% endif %>

The new version is at

http://scott.sauyet.com/Tiddlywiki/Demo/KingJamesBible/v3/

with other information in

http://scott.sauyet.com/Tiddlywiki/Demo/KingJamesBible/v3//sources

and the code that generates the tiddlers from their raw form is at

http://link.sauyet.com/kjv3.

(I may look to move this to GitHub Pages for future releases; I haven’t decided.)

I think you’re misreading $:/_/bible/procedures/chapter. That’s easy to do; I was dealing with whitespace directly, and that meant that the code formatting was awful. But spread back out temporarily, it looks like this:

<$let 
  book={{{ [<currentTiddler>get[book]] }}} 
  chapter={{{ [<currentTiddler>get[chapter]] }}} 
>
  <$list filter="[tag[Verse]] :filter[book<book>] :filter[chapter<chapter>] +[sortan[]]" counter="counter" >
    <% if [{!!new-para}match[yes]] %>
      <% if [<counter-first>!match[yes]] %>
<!--         `-------------'__ only use of `counter`   -->
        <br/><br/>
      <% endif %>
    <% endif %>
    <$text text={{{ [{!!verse}] [{!!title}] +[join[|]addprefix<open>addsuffix<close>addprefix[^^]addsuffix[^^]] }}}/>
<!--                  `------'__ code for the verse number -->
    <$text text=" "/><$text text={{{ [{!!text}] }}} />
    <$text text=" "/>
  </$list>
</$let>

The list counter is used only for some control-break logic: making sure that we don’t put extra whitespace up front. The number displayed comes from the verse field.

I’m a big fan of recursion, and I did consider it here, but I’m trying to make the most simple obvious code I can for these templates. The idea to me for this wiki is not that people would use it directly—although they’re welcome to—but that they would use it as the basis of the sort of wiki they would want to write around the (KJV version of the) bible. While recursive code is often simpler and more elegant, I think it would scare off many such users.

That makes sense. I may do that on a later refactoring.

Yes, I’m pretty sure it’s not possible.

I will try to avoid that as best I can. I have a working solution to this problem now, and I added some logical CSS hooks for formatting. I still have the <sup> tag to make the output more readable, but I don’t like it and may try to find a way around it.

<shudder>

I was definitely trying to avoid that! I think I managed it with the latest version.

Hi @Scott_Sauyet that is a very accurate picture of TiddlyWiki’s approach to rendering.

The reason why it is like this is because TiddlyWiki’s design is shaped by the requirement to be able to efficiently and selectively update the DOM when the tiddlers in the store change. Consider the way that popups are handled: the state tiddler is used updated by a button click, and the update triggers a refresh that re-evaluates the conditional rendering of the popup. To make the user experience fluid and interactive, we need that refresh cycle to work as quickly as possible.

A naive approach to the design of TiddlyWiki would be to treat the problem as a matter of stitching strings together. The result of rendering the wiki would be a massive string of HTML. If any of the tiddlers used in the rendering change then the entire HTML page would be re-rendered as another massive string of HTML which would replace the existing HTML.

Such an implementation would be grossly inefficient and performance intensive. Instead, TiddlyWiki tries to make the DOM changes required by a refresh selectively. If the only reference to the tiddler Demo is a transclusion like this <$transclude $tiddler="Demo" $mode="block"/> then ideally only those DOM nodes would be re-rendered when the tiddler “Demo” changes.

That’s why TiddlyWiki’s wikitext primitives masquerade as DOM nodes: it means that they are constrained to the same boundaries as DOM nodes.

So, that all works reasonably well, and we see decent performance even on quite underpowered hardware. As you note, we are still left with a challenge: how to generate templates that do not fit that strictly hierarchical pattern. The trick that we use is essentially to revert to the naive implementation by using a snapshot of the text of a rendering as raw HTML to saved to a file or jammed into the DOM. The magic mirror that enables this trick is the “wikified” variants of the <$view> widget or the <$wikify> widget. The core templates generally use the <$view> widget for historical reasons, but the <$wikify> widget is generally more powerful.

Thank you for the very clear explanation. It is what I suspected, and this limitation did eventually lead me to a better design with my data. (And I did have at least one additional backup plan that didn’t involve wikify: using reduce or recursion to fold the raw list into something I could use.)

I’ll have to check that out.

Thank you very much!