HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptMinor

JavaScript BB-Code transformation

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
javascriptcodetransformation

Problem

I am doing a lot of stuff with JavaScript and jQuery lately, but am not heading for clean code too much, as I am usually writing userscripts or small applications for myself.

Recently, a community I am part of announced that it will change their supported BB-Codes, as the tabmenu BB-Code had a possible safety issue. By now, hundreds of posts have been done with tabmenus and a lot of users were complaining that editing all these posts will take forever.

As I am a guy who likes to automate as much stuff as possible, I took the task and developed a small application that changes posts with the tabmenu BB-Code into a format that is supported by the forum.

Here are two examples of what the application does:

Original BB-Code:

[tabmenu]
[tab=Tab1]Tab1 Text
[tab=Tab2]Tab2 Text
[/tabmenu]


Note: tabmenu has a closing tag, tab does not and will contain all text until the next tab or until the closing [/tabmenu].

Result:

[h]Tab1[/h]Tab1 Text
[h]Tab2[/h]Tab2 Text


h turn into headlines, just as in HTML and force a linebreak.

As the tabmenu does not only support tabs, but also subtabs, here is the second example:

Original BB-Code:

[tabmenu]
[tab=Tab1]
[subtab=Subtab11]Subtab11 Text
[subtab=Subtab12]Subtab12 Text
[tab=Tab2]
[subtab=Subtab21]Subtab21 Text
[/tabmenu]


Note: If you have subtabs in you tabmenu, you can't write text into tab areas. Apart from that subtabs behave like tabs when getting their content.

Result:

[h]Tab1[/h]
[spoiler=Subtab11]Subtab11 Text
[/spoiler][spoiler=Subtab12]Subtab12 Text
[/spoiler][h]Tab2[/h]
[spoiler=Subtab21]Subtab21 Text
[/spoiler]


tabs are still being replaced with h. The behavior for subtabs is a bit different though. Here my application is taking the title from the subtab, turning it into a spoiler-Tag (not comparable with the spoiler-codes of Stack Exchange, the spoiler-BB-Code is more like an accordion) and placing the content of the subtab between the opening spoiler-Tag and the c

Solution

Your code is good, but it could be improved:

Using an enum

If you use an enum, you can avoid Magic Numbers in your switch statement:

switch (bbFormat) {
        // Depending on which format was chosen, different regex patterns are used
        case '1':


Whereas, doing:

var BB_FORMAT_TYPES = {
    NoQuotes: 1,
    DoubleQuotes: 2,
    SingleQuotes: 3
};


with:

switch (bbFormat) {
    case BB_FORMAT_TYPES.NoQuotes:
        break;
    case BB_FORMAT_TYPES.SingleQuotes:
        break;
    case BB_FORMAT_TYPES.DoubleQuotes:
        break;
}


However, using an enum is usually suited more for when the contents of each have different execution styles. In your case, it'd be better to move the code to an object, and have a single execution path referencing said object.

var object = {
        1: {
            regexTab: /\[tab=((\w|[ äöüÄÖÜ,.\-;:_#'+*!"§$%&/()=?ß^°])*)\]/g,
            regexSubTab: /\[subtab=((\w|[ äöüÄÖÜ,.\-;:_#'+*!"§$%&/()=?ß^°])*)\]((.|\s)+?((?=\[subtab)|(?=\[\/tabmenu)|(?=\[tab)))/g,
            titleTemplate: '###'
        },
        2: {
            regexTab: /\[tab="((.| )*)"\]/g,
            regexSubTab: /\[subtab="((.| )*)"\]((.|\s)+?((?=\[subtab)|(?=\[\/tabmenu)|(?=\[tab)))/g,
            titleTemplate: '"###"'
        },
        3: {
            regexTab: /\[tab='((.| )*)'\]/g,
            regexSubTab: /\[subtab='((.| )*)'\]((.|\s)+?((?=\[subtab)|(?=\[\/tabmenu)|(?=\[tab)))/g,
            titleTemplate: "'###'"
        }
    };


Chaining:

Instead of having the replace on each line, try using chaining:

input = input.replace(regexSubTab, '[spoiler=' + titleTemplate.replace('###', '$1') + ']$3[/spoiler]');
                 .replace(regexTab, '[h]$1[/h]');
                 .replace('[tabmenu]', '')
                 .replace('[/tabmenu]', '');


that way you can avoid looking up and writing to the input variable each time.

Code Snippets

switch (bbFormat) {
        // Depending on which format was chosen, different regex patterns are used
        case '1':
var BB_FORMAT_TYPES = {
    NoQuotes: 1,
    DoubleQuotes: 2,
    SingleQuotes: 3
};
switch (bbFormat) {
    case BB_FORMAT_TYPES.NoQuotes:
        break;
    case BB_FORMAT_TYPES.SingleQuotes:
        break;
    case BB_FORMAT_TYPES.DoubleQuotes:
        break;
}
var object = {
        1: {
            regexTab: /\[tab=((\w|[ äöüÄÖÜ,.\-;:_#'+*!"§$%&/()=?ß^°])*)\]/g,
            regexSubTab: /\[subtab=((\w|[ äöüÄÖÜ,.\-;:_#'+*!"§$%&/()=?ß^°])*)\]((.|\s)+?((?=\[subtab)|(?=\[\/tabmenu)|(?=\[tab)))/g,
            titleTemplate: '###'
        },
        2: {
            regexTab: /\[tab="((.| )*)"\]/g,
            regexSubTab: /\[subtab="((.| )*)"\]((.|\s)+?((?=\[subtab)|(?=\[\/tabmenu)|(?=\[tab)))/g,
            titleTemplate: '"###"'
        },
        3: {
            regexTab: /\[tab='((.| )*)'\]/g,
            regexSubTab: /\[subtab='((.| )*)'\]((.|\s)+?((?=\[subtab)|(?=\[\/tabmenu)|(?=\[tab)))/g,
            titleTemplate: "'###'"
        }
    };
input = input.replace(regexSubTab, '[spoiler=' + titleTemplate.replace('###', '$1') + ']$3[/spoiler]');
                 .replace(regexTab, '[h]$1[/h]');
                 .replace('[tabmenu]', '')
                 .replace('[/tabmenu]', '');

Context

StackExchange Code Review Q#116563, answer score: 2

Revisions (0)

No revisions yet.