Can we run a regex replace at render time?

Thanks! Sure enough - if I remove the wikify widget and replace <<wikitext>> with <<filteredText>>, that still works!

You mean the list of searches and their replacements, or something else?

Sorry, I don’t recall now, but believe I was hinting at what you said here;

  • I think I mistook this for using $:/tags/ViewTemplate

Of course once fully developed we could use the “Story Tiddler” cascade instead.

1 Like

Thank you Scott, this solution (by hoelzro) is worth documenting. I put a note to myself.
It behaves like a customized tiny parser! I am thinking powerful small tools can be created based on this;-)

1 Like

Oh, interesting - I’ve only ever used the view template body cascade!

ViewTemplate/recipe can be more compactly written like this:

<$let filteredText={{{ [{!!text}search-replace[3/4],[¾]] }}}>
<<filteredText>>
</$let>
  • Eliminate $wikify (as noted by @Mohammad)
  • Use $let instead of $set
  • Use {!!text} instead of is[current]get[text]

-e

1 Like

I’m finally getting a chance to try this, and I’ve run into a problem. Whether I use just <<filteredText>> or wrap it in <<wikify>>, I’m still getting out plain text. But I want to wikify the results.

Thus if my tiddler looks like this:

!! Ingredients

* 2 egg whites
* 3/4 cup sugar
* 5 drops oil of wintergreen
* 1/8 tsp cream of tartar
* Red food coloring
* 6 oz mini chocolate chips


!! Instructions

(more here)

I would like to have rendered:

Ingredients

  • 2 egg whites
  • 34 cup sugar
  • 5 drops oil of wintergreen
  • 18 tsp cream of tartar
  • Red food coloring
  • 6 oz mini chocolate chips

Instructions

(more here)

But instead, I get

Ingredients2 egg whites3⁄4 cup sugar5 drops oil of wintergreen1⁄8 tsp cream of tartarRed food coloring6 oz mini chocolate chipsInstructions(more here)

And if I try

<$let filteredText={{{ [{!!text}search-replace:g:regexp[\b(\d+)\/(\d+)\b],[^^$1^^&frasl;,,$2,,]] }}}>
<$transclude $variable="filteredText" mode="block"/>
</$let>

I get

!! Ingredients * 2 egg whites * 3⁄4 cup sugar * 5 drops oil of wintergreen * 1⁄8 tsp cream of tartar * Red food coloring * 6 oz mini chocolate chips !! Instructions (more here)


This looked so promising, but I really seem stuck. Any suggestions?

Obviously, it’s your call, Scott…

My philosophy is, if the rendering is a regular tiddler (yours is) then I’ll consider the <$wikify> widget. If, however, the rendering is inside a loop ($list) I’ll avoid the <$wikify> widget.

Like I said, your call.

I have a similar need in my wikis, rendering search-term matches throughout a tiddler. I use <$wikify>.

If there is a way I can pull it out, I’m all ears.

I don’t think you are getting plain text. I think the parsing is only recognizing inline syntax (add bold or some other inline markup and you’ll see). The list syntax and heading syntax is only recognized in block mode.

Why it is not parsing in block mode is a mystery to me (explained in the edit at the end).

I was able to get it to parse as desired using these two approaches:

<$let filteredText={{{ [{!!text}search-replace:g:regexp[\b(\d+)\/(\d+)\b],[^^$1^^&frasl;,,$2,,]] }}}>
<$transclude $variable="filteredText">

</$transclude>
</$let>

and (the blank line after $let puts the parser in block mode)

<$let filteredText={{{ [{recipe!!text}search-replace:g:regexp[\b(\d+)\/(\d+)\b],[^^$1^^&frasl;,,$2,,]] }}}>

<<filteredText>>
</$let>

But this did not work:

<$let filteredText={{{ [{recipe!!text}search-replace:g:regexp[\b(\d+)\/(\d+)\b],[^^$1^^&frasl;,,$2,,]] }}}>

<$transclude $variable="filteredText" mode="block"/>
</$let>

Edit: I see the issue now. The attribute on transclude should be $mode, not mode

Well, the problem is that none of this is working. They’re all giving results very different from what I’d expect.

But I did get the technique mentioned by @btheado to work just now, and I’ll write that up in a minute.

D’oh! But I did try playing with spacing for this, and kept failing. I’m really not sure why.

I may go back to this soon, but for the moment, I just got your earlier suggestion working, adding a wikirule. It needs some cleanup, but for the moment, I got it working with this:

$__community_recipes_core_modules_parsers_wikiparser_rules_fraction.js.json (1.3 KB)

(This requires save/refresh to see it working, but if you do so, just create a tiddler with some fractions in it, such as 1/4 + 1/2 = 3/4 and see the prettier formatting.)

This is the content:

/*\
title: $:/community/recipes/core/modules/parsers/wikiparser/rules/fraction.js
type: application/javascript
module-type: wikirule

Wiki text inline rule for prettifying simple fractions.

Turns, say, "3/4" into <sup>3</sup>⁄<sub>4</sub>

\*/
(function(){

/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";

exports.name = "fraction";
exports.types = {inline: true};

exports.init = function(parser) {
	this.parser = parser;
	// Regexp to match
	this.matchRegExp = /\b(\d+)\/(\d+)\b/mg;
};

exports.parse = function() {
	// Extract the numerator and denominator
    var matches = this.parser.source.slice(this.parser.pos).match(/\b(\d+)\/(\d+)\b/);
	// Move past the match
	this.parser.pos = this.matchRegExp.lastIndex;


	// Return the sub-slash-sub elements
	return [{
		type: "element",
		tag: "sup",
		children: [{type: 'text', text: matches[1]}]
	}, {
		type: "text",
		text: "⁄"
	}, {
		type: "element",
		tag: "sub",
		children: [{type: 'text', text: matches[2]}]
	}];
};

})();

It needs clean-up because of the duplication between two regexes that differ only by their flags; there should be a common source of truth there. My first attempt broke it, and I reset back to this. I will get back to it soon, but now it’s time to start New Years celebration. I will also go back to try the other solution as well, because it might be nice to target only Recipe tiddlers or some such and not all wikitext. (Or not, I’m not sure which I’d prefer yet.)


Thank you everyone for your help!

I just had a thought, and tried just replacing / entered with the keyboard with the aforementioned &frasl; however as a Unicode character.

  • The result was surprisingly useful.
  • I think the Unicode translation expects to do what we want, and we get it.
  • I then generalised it to units + fractions, even a formula
\function fractions(number) [<number>split[ ]] +[search-replace[/],[⁄]] +[join[ ]]

<<fractions "1 1/3">>
<<fractions "1/4 + 1/2 = 3/4">>

Giving;

Snag_5b0585c2

Note:

  • In this case the rendering is done at the point of displaying the output.

[Edit]

<<fractions "Some test which happens to contain 1 3/4 a fraction">>

This also works well

  • I can see some ways to make this even easier to use.

[End Edit]

[2nd Edit]
We can combine other filters to build something like this, according to the content of a string.

\function enhance.string(string) [<string>] +[search-replace[/],[⁄]] +[sentencecase[]] +[join[ ]]

<<enhance.string "some test which happens to contain 1 17/18 a fraction and sentence case.">>
  • In fact I think it may be safe to “enhance. String” before saving. Eg when users enters it.
  • Another advantage may be once we are using this alternate "/’ ie “⁄” we can use that to delimit and calculate with it.
  • Or convert to decimal.
\function quotient(dividend divisor) [<dividend>divide<divisor>]
<<quotient 1 2>>

Include whole number

\function quotient(dividend divisor whole:"1") [<dividend>divide<divisor>multiply<whole>]
<<quotent  1 2 3>>

Gives 1.5

Now I am looking at how to first parse these values to present to the functions

[end 2nd/3rd Edit]

How much does this address the outstanding requirements?

Good catch, and thanks for the fix (TIL about <$transclude $variable .../>)! I’ve incorporated that into my little demo wiki, along with @EricShulman’s feedback.

Just because I enjoy fun TiddlyWiki “Brain Age” exercises.

In case of any use, this is old-school TiddlyWiki (none of the new-fangled stuff):

(code below the image)

\define rE() \b(\d+)\/(\d+)\b
\define fmt() ^^$1^^/,,$2,,

<$let srcText={{Some Recipe}}>
<$wikify name="fmtText" text={{{ [<srcText>search-replace:g:regexp<rE>,<fmt>] }}} mode="inline" output="html">

<<fmtText>>
</$wikify>
</$let>

I think that is quite wonderful.

Just because I try to minimize cognitive load by using the least amount of TiddlyWiki features possible, here’s something that is otherwise no better and no worse (i.e. it is just sticking to features that I regularly use), involving CSS and ViewTemplate.

RecipeTiddlers.json (885 Bytes)

image

2 Likes

That is fascinating to see. I didn’t know Unicode did that! I’m curious to find its limits.

The fraction texts it generates are smaller than the ones I’ve been creating. There are times when that would be perfect. I think I prefer the larger ones for my recipe work, but I will remember this technique!

It’s not really suitable for what I want to do, but it is clearly very useful on its own. For me, I simply don’t want the user to have to type <<fraction "1/3">>. I would prefer for the user to simply type 1/3. But I won’t forget this facility; there are times when I might really want it.

Oh, interesting, I’ve used [data-tags*="something"] .tc-tiddler-body to attach certain CSS before, but I’ve never thought of it as a simple way to hide the whole body. Nice!

I’m curious as to your choice to extract the regex match and replacements as separate macros. There are times of course when that might be necessary based on their content. But it’s not necessary here. Is this a best practice to you? Just a habit? Something else?

1 Like

Most of the time and for all things, I’m a zealous componentizer.

In this particular case, it is also coincidentally an instance of “I don’t know of any other 5.2.3-and-earlier way to do that with macros”, and I’m really not interested in alternative approaches post 5.2.3. (I stick to the subset of techniques/features that handle anything I might want to do. (Travel light in the context of the things I know about and regularly use.)

2 Likes

I’ve created a new thread that captures the main results of this one, but should be easier to find if people are looking for how to create pretty fractions.

2 Likes

That macro was only to show the result. My intention would be to hide the conversion from one / to the other from the user, perhaps an action on edit.

  • as demonstrated perhaps with other formatting applied.

I like the smaller form of fractions but I can see why larger forms would be needed.

I would not be supprised if there are other unicode symbols that many help. I will let you know if I find one.

This reformatting when saving from edit, is another mechanisium we can use, along with the others in this thread, even doing maths and or converting units at field edit time.