Skip to content

Commit

Permalink
Merge pull request #5197 from inception-project/feature/5196-Improve-…
Browse files Browse the repository at this point in the history
…display-of-plain-text-files-in-HTML-editor

#5196  - Improve display of plain text files in HTML editor
  • Loading branch information
reckart authored Dec 1, 2024
2 parents c28ea26 + 8fb379f commit cf8241f
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,19 @@

import static java.lang.invoke.MethodHandles.lookup;
import static java.util.Optional.ofNullable;
import static javax.xml.XMLConstants.DEFAULT_NS_PREFIX;
import static org.slf4j.LoggerFactory.getLogger;
import static org.springframework.http.HttpStatus.OK;
import static org.springframework.http.MediaType.IMAGE_GIF;
import static org.springframework.http.MediaType.IMAGE_JPEG;
import static org.springframework.http.MediaType.IMAGE_PNG;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.StringWriter;
import java.security.Principal;
import java.util.Locale;
import java.util.Optional;

import javax.xml.XMLConstants;

import org.apache.commons.lang3.StringUtils;
import org.apache.uima.cas.CAS;
import org.dkpro.core.api.xml.type.XmlDocument;
Expand Down Expand Up @@ -64,7 +62,6 @@
import de.tudarmstadt.ukp.inception.externaleditor.policy.DefaultHtmlDocumentPolicy;
import de.tudarmstadt.ukp.inception.externaleditor.policy.SafetyNetDocumentPolicy;
import de.tudarmstadt.ukp.inception.externaleditor.xml.XmlCas2SaxEvents;
import de.tudarmstadt.ukp.inception.io.xml.dkprocore.Cas2SaxEvents;
import de.tudarmstadt.ukp.inception.support.wicket.ServletContextUtils;
import jakarta.servlet.ServletContext;

Expand All @@ -87,6 +84,7 @@ public class XHtmlXmlDocumentViewControllerImpl
private static final String BODY = "body";
private static final String HEAD = "head";
private static final String P = "p";
private static final String SPAN = "span";

private final DocumentService documentService;
private final DocumentStorageService documentStorageService;
Expand Down Expand Up @@ -160,44 +158,44 @@ public ResponseEntity<String> getDocument(@PathVariable("projectId") long aProje
// If the CAS contains an actual HTML structure, then we send that. Mind that we do
// not inject format-specific CSS then!
if (casContainsHtml) {
var xml = maybeXmlDocument.get();
startXHtmlDocument(rawHandler);

var serializer = new XmlCas2SaxEvents(xml, finalHandler);
serializer.process(xml.getRoot());

renderXmlContent(finalHandler, maybeXmlDocument.get());
endXHtmlDocument(rawHandler);
return toResponse(out);
}

startXHtmlDocument(rawHandler);

rawHandler.startElement(null, null, HTML, null);

renderHead(doc, rawHandler);

rawHandler.startElement(null, null, BODY, null);
if (maybeXmlDocument.isEmpty()) {
// Gracefully handle the case that the CAS does not contain any XML structure at all
// and show only the document text in this case.
var atts = new AttributesImpl();
atts.addAttribute("", "", "class", "CDATA", "i7n-plain-text-document");
rawHandler.startElement(null, null, BODY, atts);
renderTextContent(cas, finalHandler);
rawHandler.endElement(null, null, BODY);
}
else {
rawHandler.startElement(null, null, BODY, null);

var formatPolicy = formatRegistry.getFormatPolicy(doc);
var defaultNamespace = formatPolicy.flatMap(policy -> policy.getDefaultNamespace());

if (defaultNamespace.isPresent()) {
finalHandler.startPrefixMapping(XMLConstants.DEFAULT_NS_PREFIX,
defaultNamespace.get());
finalHandler.startPrefixMapping(DEFAULT_NS_PREFIX, defaultNamespace.get());
}

renderXmlContent(doc, finalHandler, aEditor, maybeXmlDocument.get());
renderXmlContent(finalHandler, maybeXmlDocument.get());

if (defaultNamespace.isPresent()) {
finalHandler.endPrefixMapping(XMLConstants.DEFAULT_NS_PREFIX);
finalHandler.endPrefixMapping(DEFAULT_NS_PREFIX);
}

rawHandler.endElement(null, null, BODY);
}
rawHandler.endElement(null, null, BODY);

rawHandler.endElement(null, null, HTML);

Expand Down Expand Up @@ -229,34 +227,43 @@ private void renderHead(SourceDocument doc, ContentHandler ch) throws SAXExcepti
ch.endElement(null, null, HEAD);
}

private void renderXmlContent(SourceDocument doc, ContentHandler ch, Optional<String> aEditor,
XmlDocument aXmlDocument)
throws IOException, SAXException
private void renderXmlContent(ContentHandler ch, XmlDocument aXmlDocument) throws SAXException
{
Cas2SaxEvents serializer = new XmlCas2SaxEvents(aXmlDocument, ch);
var serializer = new XmlCas2SaxEvents(aXmlDocument, ch);
serializer.process(aXmlDocument.getRoot());
}

private void renderTextContent(CAS cas, ContentHandler ch) throws SAXException
{
var lineAttribs = new AttributesImpl();
lineAttribs.addAttribute("", "", "class", "CDATA", "data-i7n-tracking");

var text = cas.getDocumentText().toCharArray();
ch.startElement(null, null, P, null);
ch.startElement(null, null, SPAN, lineAttribs);

var lineBreakSequenceLength = 0;
for (int i = 0; i < text.length; i++) {
if (text[i] == '\n') {
lineBreakSequenceLength++;
ch.endElement(null, null, SPAN);
ch.startElement(null, null, SPAN, lineAttribs);
}
else if (text[i] != '\r') {
if (lineBreakSequenceLength > 1) {
ch.endElement(null, null, SPAN);
ch.endElement(null, null, P);
ch.startElement(null, null, P, null);
ch.startElement(null, null, SPAN, lineAttribs);
}

lineBreakSequenceLength = 0;
}

ch.characters(text, i, 1);
}

ch.endElement(null, null, SPAN);
ch.endElement(null, null, P);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ html > body {
cursor: col-resize;
}

.i7n-plain-text-document {
white-space: pre-line;
}

.i7n-wrapper {
position: relative;
line-height: 1.8;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,7 @@ export class ApacheAnnotatorVisualizer {
const startTime = new Date().getTime()
this.renderHighlight(span, begin, end, attributes)
const endTime = new Date().getTime()
console.debug(`Rendering span with size ${end - begin} took ${Math.abs(endTime - startTime)}ms`)
// console.debug(`Rendering span with size ${end - begin} took ${Math.abs(endTime - startTime)}ms`)
} else {
// Try optimizing for long spans to improve rendering performance
let fragmentCount = 0
Expand All @@ -400,7 +400,7 @@ export class ApacheAnnotatorVisualizer {
fragmentCount++
}
const endTime = new Date().getTime()
console.debug(`Rendering span with size ${end - begin} took ${Math.abs(endTime - startTime)}ms (${fragmentCount} fragments)`)
// console.debug(`Rendering span with size ${end - begin} took ${Math.abs(endTime - startTime)}ms (${fragmentCount} fragments)`)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export type ViewportTrackerOptions = {
}

export const NO_TRACKING_CLASS = 'data-i7n-no-tracking'
export const TRACKING_CLASS = 'data-i7n-tracking'

export class ViewportTracker {
private _visibleElements = new Set<Element>()
Expand Down Expand Up @@ -68,6 +69,10 @@ export class ViewportTracker {
}

private shouldTrack (element: Element): boolean {
if (element.classList.contains(TRACKING_CLASS)) {
return true
}

if (this.options?.ignoreSelector && element.matches(this.options.ignoreSelector)) {
return false
}
Expand Down

0 comments on commit cf8241f

Please sign in to comment.