wrapWithStartAndEnd method

void wrapWithStartAndEnd(
  1. TagOperation op, [
  2. String? tagWithouSelection
])

Wraps the current text-selection with the provided tags. If no text is selected, an empty tag-pair is inserted at the current cursor position. If the field is not focused, the empty tag-pair is appended to the current text.

Start- and End-Tag do not have to be the same, allowing properties in the tag.

Implementation

void wrapWithStartAndEnd(TagOperation op, [String? tagWithouSelection]) {
  _cache();
  if (selection.baseOffset == selection.extentOffset) {
    value = value.copyWith(
      text: value.text + (tagWithouSelection ?? "\n${op.startTag}"),
    );
    return;
  }

  op.setSelection(selection);

  NodeV2 tree = Parser().parse(text);

  int opStart = op.start!;
  int opEnd = op.end!;

  // pass 1: split only partly affected nodes into new simple nodes
  List<SimpleNode> affectedNodes = tree.getNodesInSelection(opStart, opEnd);
  _splitOnlyPartiallySelectedNodes(affectedNodes, opStart, opEnd);

  // pass 2: apply new tag to all (now only full-selection) nodes
  affectedNodes = tree.getNodesInSelection(op.start!, op.end!);
  List<SimpleNode> changedNodes = [];
  _debug('affectedNodes ${affectedNodes.length}');

  for (SimpleNode affectedNode in affectedNodes) {
    NodeV2 affectedParent = affectedNode.parent!;

    // selection fully contains a node -> insert the attribute in its parent
    _debug(
        'isFullySelected  $opStart, $opEnd: ${affectedNode.isFullySelected(opStart, opEnd)}');
    if (affectedNode.isFullySelected(opStart, opEnd)) {
      int offset = _insertTagNodeBetween(affectedParent, affectedNode, op);

      // apply the offset to all nodes and the selection end
      _applyOffsetToNodes(affectedNode.root, offset, affectedNode);
      opEnd += offset;

      changedNodes.add(affectedNode);
    }
  }

  if (changedNodes.isNotEmpty) {
    int iStart = changedNodes.map((e) => e.textIndexStart).reduce(min);
    int iEnd = changedNodes.map((e) => e.textIndexEnd).reduce(max) + 1;

    if (editorFocusNode != null) {
      editorFocusNode!.requestFocus();
      value = value.copyWith(
        text: tree.toHtml(),
        selection: TextSelection(baseOffset: iStart, extentOffset: iEnd),
      );
    }
  } else {
    value = value.copyWith(
      text: tree.toHtml(),
    );
  }
}