Can we run a regex replace at render time?

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.

Some of the unicode examples do not work with my ubuntu 22.04 laptop.

See: No. 4, 8 and 9

@pmario the 4th relates to the fonts available to the browser, I think Noto fonts would fix it. But the 8th and 9th is as it should be 1/n

  • What do you see wrong?

I might eventually get there, but I want to be cognizant of something @Mark_S (IIRC) pointed out in another thread, that we don’t want to turn entering ingredients into a major chore. Because in going through my recipes, I’ve realized that ingredients lists are not as simple as 2 eggs or 1/4 cup cream. They often embed a bit of instructions, and have other details included:

2 (packed) cups grated sharp cheddar
8 ounces feta, crumbled fine
1 (8-ounce) block of feta, crumbled fine
2 fist-sized potatoes, sliced into 1/4" sections
2 medium red or white onions, sliced thin
1 medium onion, diced
1 cup coarsely chopped yellow onion 
...etc.

Trying to delineate fields for such expressions would be challenging. Trying to write a general parser for it would be well-nigh impossible. But they’re easy to enter as plain text.

Slight topic switch…

For whatever reason, that exchange put me in mind of @pmario’s custom parser stuff. I used to enjoy reading the exchanges between him, @TW_Tones and @twMat.

@pmario what happened to that stuff? I’m sure @Scott_Sauyet would enjoy reading it…

To keep it simple pasting a list of ingredients and even whole recipies into the text field is the most flexible.

Search can help.

However we then have the opportunity to add value through meta data and curation.

Lets say I like having people over for dinner then I may select a number of dishes I have found popular and easy to multiply to feed more people.

  • with those recipies I would be happy transfer the key ingredients into seperate entries with qty and units

then I can select and create a list to check my cupboards or a shopping list.

  • or list what i have and identify what i can cook.

To me we need to keep in mind how we can help make it easy to tap into more sophisticated uses.

Let people be casual, store simple fuzzy data but give them the tools to match what their motivations drives them to do.