Известно, насколько негибкий и неоднозначный execCommand.
Альтернативой являются объекты Range, TextRange и пользовательское выделение Selection, но разобраться с ними не так просто.
Пример из основ, пока что для всех браузеров, кроме IE:
// получить range-объект из выделенного текста можно так
var sel = document.getSelection().getRangeAt(0);
// обернуть выделенный текст (range-объект) тегом
sel.surroundContents(document.createElement('h1'));
Вопрос: как проверять, в каком теге (тегах) уже находится выделенный текст, чтоб не получить многократное оборачивание?
<div contenteditable="true">
<p>First paragraph</p><p>Second paragraph. <b>Bold text</b>.</p>
<div>