Re-creating underline/bold commands with custom schema

Apologies for posting 2 questions, though I will try to contribute in future as well :). For now, I have a custom schema where text-decoration like underline is not a mark, but an attribute for a span.

Therefore, I need to recreate the menuItem commands, such as bold and underline. This is my amateur attempt so far, which appears to work when I log $from.parent, but does not render on the view. Would you mind checking my mistakes? I imagine there are multiple. Many thanks

   export const textDecoration = (nodeType, attrs) => {
      // attrs = 'underline' for example
      return (state, dispatch) => {
        let newAttrs = attrs
        const { $from, $to } = state.selection
        // toggle
        if (attrs === $from.parent.attrs.style.textDecoration) {
          newAttrs = 'none'
        }
        const allAttrs = $from.parent.attrs.style
        allAttrs.textDecoration = newAttrs
        // if surrounded by span at both sides of selection, add attrs to existing parent span
        if ($from.pos === $from.before($from.depth) + 1 && $to.pos === $to.after($to.depth) - 1) {
          if ($from.parent.type.name === nodeType.name) {
            console.log('change it')
            const tr = state.tr.setNodeMarkup($from.before($from.depth), nodeType, allAttrs)
            dispatch(tr.scrollIntoView())
          }
        } else {
          // if not surrounded, get all inner spans and add attrs
          // unfinished
          dispatch(wrapIn(nodeType, allAttrs))
        }
        return true
      }
    }

Have you tried just copying markItem (and related functions) from the example-setup package?

Thanks Marjin. With the mark-related commands it’s a lot simpler because you are just updating the mark. In my case I’m using a MS Word approach where text styling is stored in the attributes which in turn style a span node for each fragment of styled text.

The downside of this is every scenario has to be handled, where the user can select any combination of parts of nodes, for each basic menuItem (bold, italic etc). Praise be to the Mirror.