Additional BBCode Support [RELEASED]

Fixes to BBCode rendering within server info panes and text chat

6 Likes

@Adam

Will this fix URL BBCode? :smiley:

1 Like

Will there be more BB-Codes supported, or just the ones already supported in TS3?

Is there any chance to get a complete list of all available format options?

1 Like

Any plans on the TS3 side to support the markdown supported in TS5 for so we can move formatting to the new tools without negative visual impacts for older client?

4 Likes

Is the TeamSpeak5 client supposed to use the BBCode element [SIZE] sometime?

It looks like the client isn’t build to support larger text sizes. :face_with_raised_eyebrow:

1 Like

In my opinion support for BBCodes should be dropped or atleast only a few things like color should be kept.

Forums started to drop them (like discourse) and multiple messengers like discord for example support those. Because other Messengers/Editors support markdown most people are already familiar with them.

As long TeamSpeak 5 gets support for more markdown feature nearly everything what BBCodes can do are able to be replaced.

(Would like to see support for tables with markdown btw)

3 Likes

I do agree with you.
But like you have said the color element should stay.

I was asking about the [SIZE] element support to get an offical statement by the staff.

Why?

Since TeamSpeak3 and 5 will overlap some time it makes sense to remove the SIZE element in any channel description and stopping TeamSpeak5 from displaying the [SIZE] element.

It would be the best way in my opinion TeamSpeak5 just hides the [SIZE] [/SIZE] elements.
(any other elements not being supported in TeamSpeak5, too - e.g. [hr])

3 Likes
[Update 5.0.0-beta20]
Additionally, there are some improvements to bbcode (support for size and hr tags)

Nice to read this!
A big thanks. :heart:

4 Likes

I guess one of the next BBCodes to look into would be:

[list]
[*]list item
[/list] 
2 Likes

Actually, lists are way easier to build with Markdown and I think all the BBCode support was only added to support legacy TeamSpeak 3 markup.

Right now, it looks like the new client is getting a complete BBCode parser and that kinda defeats the purpose of Markdown.

5 Likes

Only leaving as BBCode since TS3 has no support for markdown at this time and is the client most users still use. After [new]TS goes stable, or if markdown support is added to TS3, I plan to update those.

1 Like

I had an idea I consider to be a better option as far as channel description BBCode/Markdown support goes: Adding tags to filter out content based on the client viewing the channel description.

  • For content targeting TS3 wrap it in something like <ts3bbc> only for TS3 client with FULL BBCode support </ts3bbc>
  • For content targeting NewTS wrap it in something like [tsmd] only for new TS with markdown support [/tsmd]

Of course both would remove the tags for content they show so you never see any content filtering tags, unless it is unpaired or in a code block for NewTS.

Example use case is if you have channels with directions on how to do something on a server you can give them only the directions they need for the client version they are connected to the server with.

Is possible
public class ParsingTool
{
	const string tsTargetBlockStart = "[tsmd]", tsTargetBlockEnd = "[/tsmd]",
		ts3TargetTagStart = "<ts3bbc>", ts3TargetTagEnd = "</ts3bbc>",
		codeBlockMultiLine = "`"+"``" /* Broken up so that it may be pasted in multiline code block using markdown without this breaking that */ , codeBlockInline = "`",
		extractCodeSubString = "[codeIdx{0}]";

	public static void SampleUsage()
	{
		string sourceTest = "This is a sample for <ts3bbc>TeamSpeak3</ts3bbc>[TSMD]The New TeamSpeak. Now with code sample: Use `<ts3bbc>Show to TS3</ts3bbc>` to hide from New TS.[/tsmd]";
		string workingCopy = sourceTest;
		bool result = CleanForTS3(ref workingCopy);
		workingCopy = sourceTest;
		result = CleanForNewTs(ref workingCopy);
	}
	public static bool CleanForTS3(ref string cleanme)
	{
		try
		{
			string Updated = CleanTargetClientMarks(cleanme, tsTargetBlockStart, tsTargetBlockEnd, ts3TargetTagStart, ts3TargetTagEnd);
			cleanme = Updated;
		}
		catch (Exception ex)
		{ return false; }
		return true;
	}
	public static bool CleanForNewTs(ref string cleanme)
	{
		try
		{
			string Updated = ExtractCodeBlocks(cleanme, out List<string> ExtractedCode);
			Updated = CleanTargetClientMarks(Updated, ts3TargetTagStart, ts3TargetTagEnd, tsTargetBlockStart, tsTargetBlockEnd);
			Updated = InjectCodeBlocks(Updated, ExtractedCode);
			cleanme = Updated;
		}
		catch (Exception ex)
		{ return false; }
		return true;
	}
	private static string ExtractCodeBlocks(string pullCodeFrom, out List<string> RemovedCodes)
	{
		RemovedCodes = new List<string>();
		pullCodeFrom = ExtractCode(pullCodeFrom, codeBlockMultiLine, ref RemovedCodes); 
		pullCodeFrom = ExtractCode(pullCodeFrom, codeBlockInline, ref RemovedCodes);
		return pullCodeFrom;
	}
	private static string ExtractCode(string pullCodeFrom, string codeDelim, ref List<string> RemovedCodes)
	{
		int firstPart = pullCodeFrom.IndexOf(codeDelim);
		while (firstPart >= 0)
		{
			int secondPart = pullCodeFrom.IndexOf(codeDelim, firstPart + codeDelim.Length);
			if (secondPart < 0) //Unpaired opening tag, ignore it
			{ break; }
			string removedBlock = pullCodeFrom.Substring(firstPart, secondPart + codeDelim.Length - firstPart);
			pullCodeFrom = pullCodeFrom.Replace(removedBlock, string.Format(extractCodeSubString, RemovedCodes.Count));
			RemovedCodes.Add(removedBlock);
			firstPart = pullCodeFrom.IndexOf(codeDelim);
		}
		return pullCodeFrom;
	}
	private static string InjectCodeBlocks(string pushCodeTo, List<string> InjectCode)
	{
		for (int x = InjectCode.Count - 1; x >= 0; x--)
		{ pushCodeTo = pushCodeTo.Replace(string.Format(extractCodeSubString, x), InjectCode[x]); }
		return pushCodeTo;
	}
	private static string CleanTargetClientMarks(string parseThis, string ignoreStart, string ignoreEnd, string removeStart, string removeEnd)
	{
		// Remove the current client filters first, will allow for interlacing them without breaking the other
		int ts3StartAt = parseThis.ToLower().IndexOf(removeStart);
		while (ts3StartAt >= 0)
		{
			int ts3EndAt = parseThis.ToLower().IndexOf(removeEnd);
			if (ts3EndAt < 0) // unpaired opening block, ignore it
			{ break; }
			parseThis = RemoveTextSection(parseThis, ts3EndAt, removeEnd.Length);
			parseThis = RemoveTextSection(parseThis, ts3StartAt, removeStart.Length);
			ts3StartAt = parseThis.ToLower().IndexOf(removeStart);
		}
		int tsStartAt = parseThis.ToLower().IndexOf(ignoreStart);
		while (tsStartAt >= 0)
		{
			int tsEndAt = parseThis.ToLower().IndexOf(ignoreEnd);
			if (tsEndAt < 0) //Unpaired opening tag, ignore it
			{ break; }
			tsEndAt += ignoreEnd.Length;
			parseThis = RemoveTextSection(parseThis, tsStartAt, tsEndAt - tsStartAt);
			tsStartAt = parseThis.ToLower().IndexOf(ignoreStart);
		};
		return parseThis;
	}
	private static string RemoveTextSection(string original, int start, int Length)
	{
		return (start == 0 ? "" : original.Substring(0, start))
			+ (start + Length < original.Length ? original.Substring(start + Length) : "");
	}
}
3 Likes

I was thinking about making the client filter out any tag pairs it doesn’t know while keeping the contents intact.

Given this code:

[color=#FF0000][b]Important[/b][/color]

instead of partially unparsed markup like this:

[color=#FF0000]Important[/color]

you would simply get

Important

That’s less fancy than your suggestion but maybe easier to maintain than having to format for two different clients.

1 Like

Agreed, that would be simpler, but as I pointed out my suggestion is a little beyond just the filtering unsupported tag pairs but includes being able to provide different content based on the user’s client. If you have a client using NewTS the directions for creating a channel, requesting talk power and many other task in TS3 are not relevant to that user. Likewise for a user running TS3 and directions about TheTS processes. I’m not sure all servers include support in the channels, I mostly see it on servers that restrict users to creating subchannels in one channel or include directions for requesting talk power in moderated channels. But on the community server I know we have directions for many common task. As an admin I’m fine with my view/work being a little more than my users, I want them to easily see information relevant to them, without the clutter of directions for both clients visible to them. Yes, I could have TS3 support channel and a NewTS and have the content of that channel target them, but on the community server with directions in many languages already, it would not be ideal.

Interesting side effect of my proposed idea is it makes it possible to add “editor notes” if you wrap that content with both client filter tags: <ts3bbc>[tsmd]Editor notes[/tsmd]</ts3bbc> would never show in either client, only while editing the description.

3 Likes

Does not understand HTML in channel description

Do you plan to introduce html in the future

It’s not HTML, it’s BBCode. Related topic on this.

1 Like
twitch instagram twitter facebook