Skip to main content
6 of 10
added a commented version
Arnauld
  • 206.3k
  • 21
  • 189
  • 673

JavaScript (ES12), 478 bytes

s=>(a=s.split(/(\[.+?\])/)).map(S=(s,i)=>i&1?([,C,t,,p]=/.(\/)?(\w+)(=(.+))?./.exec(s),n=`url|color|size|b|i|quote|img|u|s|code`.split`|`.indexOf(t=t.toLowerCase()),C)?!([j,p]=S[t]?.pop()||[],T=`|a href="0"||21:0"||2font-1:0"|strong||em||block1|block1><cite>0</cite|1 src="0"||u||s||1`.split`|`[n*2|!!p||1]?.replace(/\d/g,n=>[p||a[j+1],t,'span style="'][n]),c-=c&&n>8)*j&&T?a[a[j]=`<${T}>`,i]=n-6?`</${/\w+/.exec(T)}>`:a[j+1]='':0:(c+=n>8,S[t]||=[]).push([i,p]):0,c=0)&&a.join``

Attempt This Online!

Commented

s =>
// split the input string on pseudo-legal BBCode tags '[…]'
(a = s.split(/(\[.+?\])/))
// for each part s at index i
.map(S = (s, i) =>
  i & 1 ?
    // if this is a tag
    (
      // C = 'closing tag' flag, t = tag name, p = optional parameter
      [, C, t,, p] = /.(\/)?(\w+)(=(.+))?./.exec(s),
      // force t to lower case and get n = internal BBCode tag ID
      n =
      // 0   1     2    3 4 5     6   7 8 9
        `url|color|size|b|i|quote|img|u|s|code`
        .split`|`
        .indexOf(t = t.toLowerCase()),
      C
    ) ?
      // if this is a closing tag
      !(
        // attempt to retrieve j = position of the opening tag
        // and p = parameter in the opening tag
        [j, p] = S[t]?.pop() || [],
        // T = HTML tag according to n and the presence of a parameter
        T =
        //  1           3      5          6       8
          `|a href="0"||21:0"||2font-1:0"|strong||em||` +
        // 10     11                   12         14 16 18
          `block1|block1><cite>0</cite|1 src="0"||u||s||1`
          .split`|`
          [n * 2 | !!p || 1]
          // unpack: 0 -> p or a[j + 1], 1 -> t, 2 -> 'span style="'
          ?.replace(/\d/g, n => [ p || a[j + 1], t, 'span style="'][n]),
        // decrement c if it's greater than 0 and the tag is 'code'
        c -= c && n > 8
      ) * j && T ?
        // if c is not 0, j is not 0 and T is defined,
        // replace the opening tag with T
        a[a[j] = `<${T}>`, i] =
          n - 6 ?
            // if this is not an 'img' tag, update the closing tag
            // using the name extracted from T
            `</${/\w+/.exec(T)}>`
          :
            // otherwise, clear both a[j + 1] and the closing tag
            a[j + 1] = ''
      :
        // invalid tag: do nothing
        0
    :
      // opening tag: increment c if the tag is 'code'
      // and push [i, p] into this tag stack
      (c += n > 8, S[t] ||= []).push([i, p])
  :
    // this is not a tag: do nothing
    0,
  // c = code block counter, initialized to 0
  c = 0
)
// end of map(), return a[] joined
&& a.join``
Arnauld
  • 206.3k
  • 21
  • 189
  • 673