String Markdown Function Not Working

Hey, everyone. Today I was playing around with a custom chat system, and I had the idea to add custom string formatting, similar to in discord, and even on forum posts. I want to combine string formatting with the new RichText beta feature.

Example of what I want: (Spaces are there to prevent post from formatting)
** bold text ** > bold text
*italics * > italics
__ underline __ > u͟n͟d͟e͟r͟l͟i͟n͟e͟
~~ Strike Through ~~ > Strike Through

Here is how I tried to implement this:

local FormatStrings = {
	Bold = {"**","b"},
	Italics = {"*","i"},
	Underline = {"__","u"},
	Strike = {"~~","s"},
}

local function FormatText(Text)
	local Reiterate = false
	
	for _, FormatInfo in pairs (FormatStrings) do
		local s, e = string.find(Text,FormatInfo[1])
		
		if s then
			local NewText = string.sub(Text,0,s - 1)..string.sub(Text,e + 1,-1)
			local s2, e2 = string.find(NewText,FormatInfo[1])
			
			if s2 then
				Text = string.sub(Text,0,s - 1).."<"..FormatInfo[2]..">"..string.sub(NewText,1,s2 - 1).."</"..FormatInfo[2]..">"..string.sub(NewText,e2 + 1,-1)
				Reiterate = true
			end
		end
	end
	
	if Reiterate then
		FormatText(Text)
	else
		return Text
	end
end

The main problem with this function, which I do not know the cause, is it never returns a string. It constantly reiterates, over exhausting the server.

So, I have a few questions. One, what am I doing wrong? Two, how would you go about accomplishing this? I know I am not supposed to ask for code written for me, but I am clueless at this point. I would be willing to pay someone if it is a big deal to write.

If you have any suggestions, please let me know. Thanks!

  • MattPrograms

If it keeps Reiterating, then that means it’s always finding s2. Try just removing the part I quoted and returning the string after just one iteration, just for debugging; you might see some extra asterisks or underscores in the result.

Beyond that, I’d put a return before the FormatText(text) in the quote, so that it would actually return a string instead of going “ok, I’ve reached the end without any return in sight, I’ll return nil”

And if you’re not too attached to making it a recursive function, I’d suggest putting it all in a while true do loop and breaking it when there is nothing more to change - perhaps even a for i = 1,10 so that it has no opportunity to run infinitely if a malicious player discovers a way to make that happen.

Once you’ve got this function working, I suggest looking at a more mature Markdown implementation in JavaScript, and how others have done it. These ones likely only do one pass over the entire string and keep a stack of formatting symbols they’ve found in the text so far (although I haven’t looked at any implementation of it, myself, either)

I ended up using gsub. The main reason for the function not working, was because * is a special character in patterns. I added a % in front of it, problem solved. Thanks for your suggestion.