From dfd1f0cf5e521fd6721ca58bd5e79809ac7b41c6 Mon Sep 17 00:00:00 2001
From: Jacob Benz <jacob.benz@stud.h-da.de>
Date: Fri, 17 May 2024 11:13:54 +0200
Subject: [PATCH] Add lb-tag after Shift+Enter as linebreak for transcribing
 workflow

---
 .../src/js/tinymce/tinymceWrapper.ts          | 105 +++++++++++++++++-
 1 file changed, 103 insertions(+), 2 deletions(-)

diff --git a/packages/cwrc-leafwriter/src/js/tinymce/tinymceWrapper.ts b/packages/cwrc-leafwriter/src/js/tinymce/tinymceWrapper.ts
index ea4aa873..c3eabc6b 100644
--- a/packages/cwrc-leafwriter/src/js/tinymce/tinymceWrapper.ts
+++ b/packages/cwrc-leafwriter/src/js/tinymce/tinymceWrapper.ts
@@ -297,7 +297,9 @@ export const tinymceWrapperInit = function ({
     writer.event('writerKeydown').publish(event);
   };
 
-  const onKeyUpHandler = (event: KeyboardEvent) => {
+  const onKeyUpHandler = async (event: KeyboardEvent) => {
+    const { overmindState, overmindActions } = writer;
+    
     // nav keys and backspace check
     switch (event.code) {
       case 'Home':
@@ -437,7 +439,106 @@ export const tinymceWrapperInit = function ({
         if (event.shiftKey) {
           // TODO replace linebreaks inserted on shift+enter with schema specific linebreak tag
           // for now just undo the linebreak in the text
-          node.normalize();
+          // This schema specific linebreak is now lb. With this decision and our handling of lb and similiar self-closing tags below,
+          // we implicitly narrowed the scope of LEAF-Writer to TEI and TEI only.
+          if (!writer) return;
+
+          // Detect tags that can be inserted an the current position and check that lb is one of them
+          const xpath = writer.utilities.getElementXPath(node);
+          if (!xpath) return;
+          const index = 0;
+          const selection: PossibleNodesAtTargetSelection = {
+            type: 'inside',
+            xpath: xpath ?? '',
+          };
+          const request: PossibleNodesAtTarget = { xpath, index, selection };
+          // console.log(request);
+
+          const tags = await overmindActions.validator.getPossibleNodesAt(request); // get possible nodes from validator for current xpath-locattion and inside this location
+          if (!tags) { // If we did not get anythin back from the validator-worker, we have to end, since we can't check if lb is allowed.
+            node.normalize();
+            writer.event('writerKeyup').publish(event);
+            return
+          }
+          //console.log(tags)
+
+          let lbIsAllowed = false
+          tags.map(({ name, fullName, invalid, documentation }) => {
+            if (name === "lb") {
+              lbIsAllowed = true
+            }
+          })
+
+          if (lbIsAllowed === true) { // Add new lb-tag at current position
+            //console.log("Yes, we can [lb]!")
+            //console.log(curnode)
+            //console.log(writer.editor.currentBookmark)
+            //console.log(writer.editor?.selection.getBookmark(1))
+            log.info("inserting lb-tag after Shift+Enter press")
+            // Insert new lb-tag at current position (adapted code from File "tagger.ts")
+            const id = writer.getUniqueId('dom_');
+            const bookmark = writer.editor.currentBookmark
+            const tagName = "lb"
+
+            let $newlbnode: JQuery<any>;
+
+            // this is meant for user text selections
+            //@ts-ignore
+            let newlbnode = bookmark.rng.commonAncestorContainer;
+            while (
+              newlbnode.nodeType == Node.TEXT_NODE ||
+              (newlbnode.nodeType == Node.ELEMENT_NODE && !newlbnode.hasAttribute('_tag'))
+            ) {
+              newlbnode = newlbnode.parentNode;
+            }
+            $newlbnode = $(newlbnode);
+
+            // noteWrapper handling
+            let $noteWrapper: JQuery<any> | null = null;
+            const noteAttr_tag = $newlbnode.attr('_tag');
+            const entityType = noteAttr_tag
+              ? writer.schemaManager.mapper.getEntityTypeForTag(noteAttr_tag)
+              : null;
+
+
+            const editorTagName = writer.schemaManager.getTagForEditor(tagName);
+            let open_tag = `<${editorTagName} id="${id}" _tag="lb"`;
+            // We have to check if text is allowed in the tag we want to add.
+            let textallowed = writer.schemaManager.canTagContainText(tagName);
+            open_tag += ` _textallowed="${textallowed}"`;
+
+
+            const close_tag = '</' + editorTagName + '>';
+            // const close_tag = '</' + editorTagName + '>' + '\uFEFF';
+            let content = `${open_tag}${close_tag}`;
+
+            // default action = add
+            //@ts-ignore
+            writer.editor?.selection.moveToBookmark(bookmark);
+
+            //@ts-ignore
+            const range: Range = writer.editor?.selection.getRng(true);
+            const tempNode = $('<span data-mce-bogus="1">', writer.editor?.getDoc());
+            //@ts-ignore
+            range.surroundContents(tempNode[0]);
+            tempNode.replaceWith(content);
+
+            const newTag = $(`#${id}`, writer.editor?.getBody());
+            writer.event('tagAdded').publish(newTag[0]);
+
+            writer.editor?.undoManager.add();
+            // place the cursor at the end of the tag's contents
+            //@ts-ignore
+            const rng: Range = writer.editor?.selection.getRng(true);
+            //@ts-ignore
+            rng.selectNodeContents($(`#${id}`, writer.editor?.getBody())[0]);
+            rng.collapse(false);
+            writer.editor?.selection.setRng(rng);
+            
+
+          } else {
+            node.normalize();
+          }
         } else {
           // empty tag check
           // insert zero-width non-breaking space so empty tag takes up space
-- 
GitLab