Support non-verbal elements in token table view

Change-Id: I434112c4bf7014f196ad85fc4a19fe56fd1e8c3d
diff --git a/Changes b/Changes
index f7579c5..19dbc10 100755
--- a/Changes
+++ b/Changes
@@ -25,6 +25,7 @@
         - Fixed matchID transformation to deal with textSigles
           having dashes.
         - Catch timeouts in proxy.
+        - Support non-verbal elements in token table view.
 
 0.36 2019-09-19
         - Rename all cookies to be independent
diff --git a/dev/demo/matchdemo.js b/dev/demo/matchdemo.js
index 1dbf83b..437c47c 100644
--- a/dev/demo/matchdemo.js
+++ b/dev/demo/matchdemo.js
@@ -438,7 +438,7 @@
   "<span class=\"context-right\">" +
   "</span>";
 
-  // with cut
+  // with cut and verbal
   snippet = "<span class=\"context-left\"><\/span>"+
   "<span class=\"match\">" +
   "<span class=\"cutted\"><\/span>" +
@@ -467,6 +467,10 @@
   "    </span>" +
   "  </span>" +
   "</span>" +
+
+  "<span title=\"dgd/para:incident\">▮</span>" +
+  "<span title=\"dgd/para:vocal\">▮</span>" +
+  
   "<span title=\"cnx/l:fähig\">" +
   "  <span title=\"cnx/l:leistung\">" +
   "    <span title=\"cnx/p:A\">" +
diff --git a/dev/js/spec/matchSpec.js b/dev/js/spec/matchSpec.js
index a51fd78..08c0ced 100644
--- a/dev/js/spec/matchSpec.js
+++ b/dev/js/spec/matchSpec.js
@@ -129,6 +129,7 @@
       "  </span>" +
       "</span>" +
       "</mark>" +
+      "<span title=\"dgd/para:incident\">▮</span>" +
       "<span title=\"cnx/l:fähig\">" +
       "  <span title=\"cnx/l:leistung\">" +
       "    <span title=\"cnx/p:A\">" +
@@ -212,7 +213,7 @@
   var treeSnippetHierarchy =
       "<span class=\"context-left\"><\/span><span class=\"match\"><span title=\"corenlp\/c:MPN\">Leonard Maltin<\/span> schrieb: „<span title=\"corenlp\/c:S\"><span title=\"corenlp\/c:NP\">Plot <span title=\"corenlp\/c:MPN\">contrivance isn‘<mark>t<\/mark> handled badly<\/span><\/span> <span title=\"corenlp\/c:PP\">in above-average programmer<\/span><\/span>“.&lt;<span title=\"corenlp\/c:S\"><span title=\"corenlp\/c:ROOT\"><span title=\"corenlp\/c:NP\">ref&gt;''<span title=\"corenlp\/c:NP\"><span title=\"corenlp\/c:CNP\">Movie &amp;amp; Video<\/span> Guide<\/span><\/span>'', <span title=\"corenlp\/c:VP\">1996 edition, <span title=\"corenlp\/c:NP\"><span title=\"corenlp\/c:CNP\">S. 210<\/span><\/span><\/span>.<\/span><\/span><\/span><span class=\"context-right\"><\/span>";
 
-          function matchElementFactory () {
+  function matchElementFactory () {
     var me = document.createElement('li');
 
     me.setAttribute(
@@ -488,22 +489,22 @@
     it('should parse into a table (async)', function () {
       expect(table).toBeTruthy();
 
-      expect(table.length()).toBe(7);
+      expect(table.length()).toBe(8);
 
       expect(table.getToken(0)).toBe("");
       expect(table.getToken(1)).toBe("Außerdem ");
       expect(table.getToken(2)).toBe("meist");
       expect(table.getToken(3)).toBe("deutlich");
-      expect(table.getToken(4)).toBe("leistungsfähiger");
-      expect(table.getToken(5)).toBe(longString);
+      expect(table.getToken(5)).toBe("leistungsfähiger");
+      expect(table.getToken(6)).toBe(longString);
 
       expect(table.getValue(2, "cnx", "p")[0]).toBe("ADV");
       expect(table.getValue(2, "cnx", "syn")[0]).toBe("@PREMOD");
       expect(table.getValue(2, "mate", "l")[0]).toBe("meist");
       expect(table.getValue(2, "mate", "l")[1]).toBeUndefined();
 
-      expect(table.getValue(4, "cnx", "l")[0]).toBe("fähig");
-      expect(table.getValue(4, "cnx", "l")[1]).toBe("leistung");
+      expect(table.getValue(5, "cnx", "l")[0]).toBe("fähig");
+      expect(table.getValue(5, "cnx", "l")[1]).toBe("leistung");
     });
    
     it('should be rendered async', function () {
@@ -525,12 +526,13 @@
       expect(tr.children[4].classList.contains('mark')).toBeFalsy();
       expect(tr.children[5].firstChild.nodeValue).toBe('deutlich');
       expect(tr.children[5].classList.contains('mark')).toBeTruthy();
-      expect(tr.children[6].firstChild.nodeValue).toBe('leistungsfähiger');
-      expect(tr.children[6].classList.contains('mark')).toBeFalsy();
-      expect(tr.children[6].hasAttribute("title")).toBeFalsy();
-      expect(tr.children[7].firstChild.nodeValue).toBe(longString);
-      expect(tr.children[7].getAttribute("title")).toBe(longString);
-      expect(tr.children[8].classList.contains('cutted')).toBeTruthy();
+      expect(tr.children[6].firstChild.nodeValue).toBe('▮');
+      expect(tr.children[7].firstChild.nodeValue).toBe('leistungsfähiger');
+      expect(tr.children[7].classList.contains('mark')).toBeFalsy();
+      expect(tr.children[7].hasAttribute("title")).toBeFalsy();
+      expect(tr.children[8].firstChild.nodeValue).toBe(longString);
+      expect(tr.children[8].getAttribute("title")).toBe(longString);
+      expect(tr.children[9].classList.contains('cutted')).toBeTruthy();
 
       // first row
       tr = e.children[1].children[0];
@@ -541,8 +543,9 @@
       expect(tr.children[1].firstChild.nodeValue).toEqual('l');
       expect(tr.children[4].firstChild.nodeValue).toEqual('meist');
       expect(tr.children[5].firstChild.nodeValue).toEqual('deutlich');
-      expect(tr.children[6].firstChild.firstChild.nodeValue).toEqual('fähig');
-      expect(tr.children[6].lastChild.firstChild.nodeValue).toEqual('leistung');
+      expect(tr.children[6].firstChild).toBeNull();
+      expect(tr.children[7].firstChild.firstChild.nodeValue).toEqual('fähig');
+      expect(tr.children[7].lastChild.firstChild.nodeValue).toEqual('leistung');
 
       // second row
       tr = e.children[1].children[1];
@@ -553,10 +556,11 @@
       expect(tr.children[1].firstChild.nodeValue).toEqual('p');
       expect(tr.children[4].firstChild.nodeValue).toEqual('ADV');
       expect(tr.children[5].firstChild.nodeValue).toEqual('A');
-      expect(tr.children[6].firstChild.firstChild.nodeValue).toEqual('A');
-      expect(tr.children[6].lastChild.firstChild.nodeValue).toEqual('ADJA');
+      expect(tr.children[6].firstChild).toBeNull();
+      expect(tr.children[7].firstChild.firstChild.nodeValue).toEqual('A');
+      expect(tr.children[7].lastChild.firstChild.nodeValue).toEqual('ADJA');
 
-      expect(tr.children[6].firstChild.getAttribute("title")).toEqual('Adjective');
+      expect(tr.children[7].firstChild.getAttribute("title")).toEqual('Adjective');
       expect(tr.children[4].getAttribute("title")).toEqual('Adverb');
     });
 
@@ -616,6 +620,11 @@
       // expect(infotable.children[1].classList.contains('addtree')).toBeTruthy();
     });
 
+    it('should parse into a table view with non-verbal elements (sync)', function () {
+      var matchElement = matchElementFactory();
+      expect(matchElement.tagName).toEqual('LI');
+    });
+    
   });
 
   describe('KorAP.RelationsView', function () {
diff --git a/dev/js/src/match/table.js b/dev/js/src/match/table.js
index edadd0e..3ad2731 100644
--- a/dev/js/src/match/table.js
+++ b/dev/js/src/match/table.js
@@ -175,7 +175,7 @@
         // Leaf node
         // store string on position and go to next string
         else if (c.nodeType === 3) {
-          if (c.nodeValue.match(/[a-z0-9]/i)) {
+          if (c.nodeValue.match(/[a-z0-9\u25ae]/iu)) {
             this._mark[this._pos] = mark ? true : false;
             this._token[this._pos++] = c.nodeValue;
           };
diff --git a/dev/scss/main/matchinfo.scss b/dev/scss/main/matchinfo.scss
index a4e69ba..c36126f 100644
--- a/dev/scss/main/matchinfo.scss
+++ b/dev/scss/main/matchinfo.scss
@@ -58,6 +58,11 @@
   }
   td:empty {
     cursor: default;
+    // Fix for empty annotation lines:
+    &::after {
+      content: " ";
+      white-space: pre;
+    }
   }
   tr {
     outline: none;