Can we run a regex replace at render time?

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.

I’d be very interested to see how you do that. It’s not something I’ve ever tried, or ever seen done. Is there a built-in hook you can attach to, or do you have to override the “Save” button and attach your own action(s)?

That’s on my own (ever-growing!!) list of things to investigate. If you do find more, please share.

In summary, if someone were entering an ingredient they could edit the tiddler and use the default field editor. This just commits the changes to the field.

You could however;

  • Use the new Field editor cascade, with a custom edit
  • or in the view template provide an $edit or $edit-text widget

Both which can use its inputActions parameter to trigger an action and apply an “on edit parsing”, such as replacing the / and applying sentence case etc… .

  • That is, as a designer we create a mechanism to parse or reformat what the user enters, at edit time, unlike parsing at render time.
  • Once done, the value remains in this new format unless changed.
  • This could be more efficient than reformatting everytime a field value is displayed.
  • As I demonstrated with functions above we could write a set of global functions/custom filter operators you can reuse according to the field definitions.
  • May be we could also extract quantities, or units from text entered and populate a quantity field/units field.

Note: By using inputActions note that;

“Optional actions that are triggered every time an input event occurs within the input field or textarea”

  • So you want your formatter to be quick and repeatable on every key stroke.
  • Perhaps dont use it for large text areas
  • This way you do not need a separate temp field and save button,
    • But you may for larger text areas.

That probably wouldn’t work for me. I doubt that these fractions will end up in fields very often, at least not at first. I’m expecting them to be part of free-form text. I actually override field editors fairly often, so it’s clear enough how I would do this, but I don’t think it works for my case.

Well, we have one built-in, of course. Would you suggest replacing that one?

While that might be acceptable in this very specific case (especially if in the end all we end up doing is substituting / with ), I would find it a really bad habit to get into. As a user, when I want to make changes, I want to change the text I entered and not someone’s idea of an improvement to it. Imagine if every time you save, your //italic text// gets converted to <em>italic text</em> and every [[link|Target]] were rewritten as <a href="#Target">link</a>, and that’s what you’d have to edit next time. Uggh!

Here is a little example of Unicode characters and their effect;

  • 1/2 normal
  • 2 1⁄3 fraction slash
  • 3 2∕3 division slash
  • 4 3⟋4 rising diagonal
  • 5 19⧸20 big solidis
  • 6 1/5 full width solidis
  • 7÷8
  • 5➗6
  • ⅟4 Fraction Numerator One
  • Or you could just make something bigger <span style.font-size="3em">1⁄3</span> or <span style="font-size:3em;">1⁄3</span>

My chrome browser seems to recognise them all.

You could also use

  • actual superscript and subscript numbers eg Unicode U+00B2 Superscript Two ² (rather than formatting).
  • Combined with the U+00BC Vulgar Fraction One Quarter ¼ and other variants

I wonder if we could use CSS to replace / with fraction slash.

Yes, we should be able to use regex with these too.

1 Like

Keep in mind these are simply alternative approaches. Anyone designing a solution needs to make the right choices relative to their design and aesthetics.

Each to their own, I would provide an intuitive interface to enter ingredients, sure free form text at first, for copy and paste source material.

  • Also all the output Unicode I listed can just be used after a regexp or parsing action anyway.
  • Your could but it depends on your design approach.
  • I would tend to provide a recipe view template, and an edit mode in the view template view, a form you could say, to accept input.
    • This allows more data entry, customisation and presentation options.
    • In which case, not modify the default.
  • There would be no habit here, if you go through an “ingredient editor” if would just do it, and if you did not it will just look different.
  • If later you do maths on it you may need to take account of the multiple division symbols, but that many be trivial.
  • That is what tiddlywiki does now, just only on display.
  • To restate your question "Imagine if every time you save, your 1/3 [it] gets converted to 1⁄3 ". not quite the impact of your embedded html.
  • This also illustrates if you want to allow wikitext in your text that having a different for numbers 1⁄3 differentiates it from italics.

So all this is part of the design possibilities, and there are alternatives to regex at render time.