(Trying to tie up loose ends.)
Re-reading this thread reminded me of the
[r] tag that I worked on to help out jayce (and other signature designers).
I never got around to properly testing/finishing it, and I don't see me now finding the time/energy to do that, so I figured I should at least dump the last diff I made in case anyone ever wants to pick this one up:
--- /var/www/baseline/Sources/Subs.php 2011-09-17 21:59:55.000000000 +0000
+++ /var/www/modified/Sources/Subs.php 2023-06-01 16:35:10.000000000 +0000
@@ -1465,24 +1465,48 @@
'block_level' => true,
),
array(
'tag' => 'quote',
'parameters' => array(
'author' => array('match' => '(.{1,192}?)', 'validate' => 'parse_bbc'),
),
'before' => '<div class="quoteheader">' . $txt['smf239'] . ': {author}</div><div class="quote">',
'after' => '</div>',
'block_level' => true,
),
array(
+ 'tag' => 'r',
+ 'type' => 'unparsed_equals_content',
+ 'content' => '$1',
+ 'disabled_content' => '[r=$2]$1[/r]',
+ 'test' => '\d{1,3}\]',
+ 'validate' => function(&$tag, &$data, &$disabled) {
+ // Don't do anything if the tag has been disabled (just rely on 'disabled_content', above).
+ if(isset($disabled['r']))
+ return;
+ // Self-nesting won't work (the first encountered [/r] will close the outermost [r]) for this type of tag (unparsed_equals_content), so detect it and output '(r:nesting)' instead.
+ // This also (conveniently) saves me from having to think too deeply about accidentally introducing recursion-related security issues.
+ if(strpos($data[0], '[r=') !== false) {
+ $data[0] = '(r:nesting)';
+ return;
+ }
+ $count = (int)$data[1];
+ // Skip parsing if the result won't end up contributing to the output.
+ $parsed = $count > 0 ? parse_bbc($data[0]) : '';
+ // Seems prudent (considering the intended use cases for this tag) to enforce a conservative size limit, and output '(r:overflow)' when that limit is exceeded.
+ // If you replace str_repeat() with something else, then make sure to verify that the $count == 0 case is being handled correctly.
+ $data[0] = strlen($parsed) * $count <= 256 ? str_repeat($parsed, $count) : '(r:overflow)';
+ },
+ ),
+ array(
'tag' => 'right',
'before' => '<div style="text-align: right;">',
'after' => '</div>',
'block_level' => true,
),
array(
'tag' => 'red',
'before' => '<span style="color: red;">',
'after' => '</span>',
),
array(
'tag' => 'rtl',
Because I suspect (or more like
know at this point) that most of you are not going to carefully (re-)read the thread, I'll remind you what the
[r] tag (that the above diff is for) does: it's intended as a way to (non-recursively, with respect to itself) parse and then "repeat" (a given number of times) the BBCode that it wraps.
So, if you're designing a signature, and you, for example, wanted a 32-character "bar", then instead of typing:
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░You'd type:
[r=32]░[/r]It's tough to appreciate (and orthogonal to its intended purpose), but, one of the really cool things about this tag is that it (accidentally) forms a pretty natural way to add "comments" to BBCode. As in, if you ask it to repeat something
zero times, then you'll have a construct that persists within the BBCode of a post/PM/signature, but one that won't survive the translation into (X)HTML:
[r=0]Made by jayce[/r]Now, there are a few obvious and not-so-obvious uses for BBCode comments, and the use case I was getting excited about back in 2023 was the one where comments could be used to embed "directives" within posts/PMs/signatures. For example, work stalled on my
thread banners idea when I realized that instead of adding new UI elements and new database columns, I could get the whole idea to work (and some other ideas, too) by defining a little "directive language" and specifying the banner-specifics with a BBCode comment (placed anywhere in the opening post of a topic).
I'm not going to unpack the whole thing now, but, perhaps this old PM will shed some light on what I had in mind:
Just sharing some thoughts I had (about the directive parser) while walking the dog.
We could base it on XML, like this (i.e. a prefix, and then ordinary XML):
[r=0]@:<threadBanner text="..." fgColor="#000" bgColor="#FFF" until="1685577599" />[/r]
I'm not sure what the XML situation in PHP is like, but I'm assuming it's all based on libxml2, and that's a lot of additional attack surface to expose.
We could also base it on S-expressions (I've written one or two embeddable lisps), but I think that might be a bit too weird for most people.
We could base it on JSON, I suppose, but same as with XML, I don't really feel like writing my own implementation, and I don't feel like combing through a ton of someone else's code to vouch for its safety.
I think something like what I proposed earlier will work out nicely, especially if we simplify it so that it only accepts strings as arguments, like this:
[r=0]@:threadBanner(text="...", fgColor="#000", bgColor="#FFF", until="1685577599")[/r]
That way, the pattern is {prefix}{identifier}{openRoundBracket}{arguments}{closeRoundBracket}, and {arguments} is a comma-separated sequence of {identifier}{equalsSign}{stringLiteral}.
That should admit a very straightforward parser that spits out an associative array, like this: ["@:cmd" => "threadBanner", "fgColor" => "#000", "bgColor" => "#FFF", "until" => "1685577599"].
Call me mad, but I would trust 30 lines of PHP that we've both looked at carefully, much more than any shifting dependency.
I was never able to convince theymos that this approach made sense (compared to, for example, implementing the "thread banners" idea in the obvious way: by emitting some new UI elements on the
action=post page, and having them affect and be affected by some new database columns).
I think the last thought I had about this before I put the whole thing to bed was to maybe break out a "comment" tag as its own thing instead of convolving it with a "repeat" tag (as in, a "repeat" tag is a difficult/complex thing to think through and justify adding, but I didn't want months/years of hemming and hawing to block the "comment" use case). Probably I'd name that tag
[rem] (for "remark"), which should ring a distant bell for anyone that's ever done much BASIC (or batch file) programming.
And that's all I have to say about that.


While I'm on the subject of "code comments", this one cracked me up pretty good:
//
// Dear maintainer:
//
// Once you are done trying to 'optimize' this routine,
// and have realized what a terrible mistake that was,
// please increment the following counter as a warning
// to the next guy:
//
// total_hours_wasted_here = 42
//

This one, too:
/**
* For the brave souls who get this far: You are the chosen ones,
* the valiant knights of programming who toil away, without rest,
* fixing our most awful code. To you, true saviors, kings of men,
* I say this: never gonna give you up, never gonna let you down,
* never gonna run around and desert you. Never gonna make you cry,
* never gonna say goodbye. Never gonna tell a lie and hurt you.
*/