Retina, 675 bytes
i`\[code](.*)\[/code]
==$1==
i`(?<!==.*)\[b](.*)\[/b](?!.*==)
<strong>$1</strong>
i`(?<!==.*)\[i](.*)\[/i](?!.*==)
<em>$1</em>
i`(?<!==.*)\[(.)](.*)\[/\1](?!.*==)
<$1>$2</$1>
i`(?<!==.*)\[color=(.*)](.*)\[/color](?!.*==)
<span style="color:$1">$2</span>
i`(?<!==.*)\[size=(.*)](.*)\[/size](?!.*==)
<span style="font-size:$1">$2</span>
i`(?<!==.*)\[url](.*)\[/url](?!.*==)
[url=$1]$1[/url]
i`(?<!==.*)\[url=(.*)](.*)\[/url](?!.*==)
<a href="$1">$2</a>
i`(?<!==.*)\[img](.*)\[/img](?!.*==)
<img src="$1">
i`(?<!==.*)\[quote=(.*)](.*)\[/quote](?!.*==)
[quote]<cite>$1</cite>$2[/quote]
i`(?<!==.*)\[quote](.*)\[/quote](?!.*==)
<blockquote>$1</blockquote>
==(.*)==
<code>$1</code>
-20 bytes: I discovered by accident that ] matches that character and it doesn't need to be escaped when it doesn't close a character class
+0 byte: fixing a typo, saved another ]
a big mess but by the first 5 minutes i already wanted to be done writing regex.
Explanation
- all exressions are case-insensitive
- First, replace all
codetags with==which is guaranteed not to appear elsewhere - I use negative look(ahead|behind) to assert the things i'm matching aren't enclosed in
==in all subsequent expressions, properly escaping whatever is in code tags (this is shorter than checking for the full[code]tag everytime) - i replace b and i tags with their respective html
- i replace the remaining 1-letter tags with the same tag as html
- i replace color and size tags (an optimization here could allow first replacing
sizewithfont-sizethen matching and replacing both but i couldn't find a way where that's shorter) - I replace urls without an
=with one that has - I replace all urls properly
- i replace all images
- i replace quotes with an
=to one without, that just contains the literal<cite>tag - I replace quote tags properly
- finally, i replace my custom
==tags with their contents in a<code>tag.