function splitWiresWithLinkNodes(wires) {
        if (RED.workspaces.isLocked()) {
            return
        }
        let wiresToSplit = wires || (RED.view.selection().links && RED.view.selection().links.filter(e => !e.link));
        if (!wiresToSplit) {
            return
        }
        if (!Array.isArray(wiresToSplit)) {
            wiresToSplit = [wiresToSplit];
        }
        if (wiresToSplit.length < 1) {
            return; //nothing selected
        }

        const history = {
            t: 'multi',
            events: [],
            dirty: RED.nodes.dirty()
        }
        const nodeSrcMap = {};
        const nodeTrgMap = {};
        const _gridSize = RED.view.gridSize();

        for (let wireIdx = 0; wireIdx < wiresToSplit.length; wireIdx++) {
            const wire = wiresToSplit[wireIdx];

            //get source and target nodes of this wire link
            const nSrc = wire.source;
            const nTrg = wire.target;

            var updateNewNodePosXY = function (origNode, newNode, alignLeft, snap, yOffset) {
                const nnSize = RED.view.calculateNodeDimensions(newNode);
                newNode.w = nnSize[0];
                newNode.h = nnSize[1];
                const coords = { x: origNode.x || 0, y: origNode.y || 0, w: origNode.w || RED.view.node_width, h: origNode.h || RED.view.node_height };
                const x = coords.x - (coords.w/2.0);
                if (alignLeft) {
                    coords.x = x - _gridSize - (newNode.w/2.0);
                } else {
                    coords.x = x + coords.w + _gridSize + (newNode.w/2.0);
                }
                newNode.x = coords.x;
                newNode.y = coords.y;
                if (snap !== false) {
                    const offsets = RED.view.tools.calculateGridSnapOffsets(newNode);
                    newNode.x -= offsets.x;
                    newNode.y -= offsets.y;
                }
                newNode.y += (yOffset || 0);
            }
            const srcPort = (wire.sourcePort || 0);
            let linkOutMapId = nSrc.id + ':' + srcPort;
            let nnLinkOut = nodeSrcMap[linkOutMapId];
            //Create a Link Out if one is not already present
            if(!nnLinkOut) {
                const nLinkOut = RED.view.createNode("link out"); //create link node
                nnLinkOut = nLinkOut.node;
                let yOffset = 0;
                if(nSrc.outputs > 1) {

                    const CENTER_PORT = (((nSrc.outputs-1) / 2) + 1);
                    const offsetCount = Math.abs(CENTER_PORT - (srcPort + 1));
                    yOffset = (_gridSize * 2 * offsetCount);
                    if((srcPort + 1) < CENTER_PORT) {
                        yOffset = -yOffset;
                    }
                    updateNewNodePosXY(nSrc, nnLinkOut, false, false, yOffset);
                } else {
                    updateNewNodePosXY(nSrc, nnLinkOut, false, RED.view.snapGrid, yOffset);
                }
                //add created node
                nnLinkOut = RED.nodes.add(nnLinkOut);
                nodeSrcMap[linkOutMapId] = nnLinkOut;
                RED.editor.validateNode(nnLinkOut);
                history.events.push(nLinkOut.historyEvent);
                //connect node to link node
                const link = {
                    source: nSrc,
                    sourcePort: wire.sourcePort || 0,
                    target: nnLinkOut
                };
                RED.nodes.addLink(link);
                history.events.push({
                    t: 'add',
                    links: [link],
                });
            }

            let nnLinkIn = nodeTrgMap[nTrg.id];
            //Create a Link In if one is not already present
            if(!nnLinkIn) {
                const nLinkIn = RED.view.createNode("link in"); //create link node
                nnLinkIn = nLinkIn.node;
                updateNewNodePosXY(nTrg, nnLinkIn, true, RED.view.snapGrid, 0);
                //add created node
                nnLinkIn = RED.nodes.add(nnLinkIn);
                nodeTrgMap[nTrg.id] = nnLinkIn;
                RED.editor.validateNode(nnLinkIn);
                history.events.push(nLinkIn.historyEvent);
                //connect node to link node
                const link = {
                    source: nnLinkIn,
                    sourcePort: 0,
                    target: nTrg
                };
                RED.nodes.addLink(link);
                history.events.push({
                    t: 'add',
                    links: [link],
                });
            }

            //connect the link out/link in virtual wires
            if(nnLinkIn.links.indexOf(nnLinkOut.id) == -1) {
                nnLinkIn.links.push(nnLinkOut.id);
            }
            if(nnLinkOut.links.indexOf(nnLinkIn.id) == -1) {
                nnLinkOut.links.push(nnLinkIn.id);
            }

            //delete the original wire
            RED.nodes.removeLink(wire);
            history.events.push({
                t: "delete",
                links: [wire]
            });
        }
        //add all history events to stack
        RED.history.push(history);

        //select all downstream of new link-in nodes so user can drag to new location
        RED.view.clearSelection();
        RED.view.select({nodes: Object.values(nodeTrgMap) });
        selectConnected("down");

        //update the view
        RED.nodes.dirty(true);
        RED.view.redraw(true);
    }
Splits selected wires and re-joins them with link-out+link-in
@param {Object || Object[]} wires The wire(s) to split and replace with link-out, link-in nodes.