Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for rich text #3

Closed
rwb27 opened this issue Oct 25, 2017 · 6 comments
Closed

Support for rich text #3

rwb27 opened this issue Oct 25, 2017 · 6 comments

Comments

@rwb27
Copy link
Owner

rwb27 commented Oct 25, 2017

This issue is to track my progress implementing rich text support.

@rwb27
Copy link
Owner Author

rwb27 commented Oct 25, 2017

Question: do I want to just assume the string inside <description> tags is safe HTML? Not sure I do... Either way, we need to allow descriptions to hold more than just plain text. I think a sensible way to proceed is to work out a way to render an Element, taking care to let through only those tags that are safe.

@rwb27
Copy link
Owner Author

rwb27 commented Oct 26, 2017

I've now succeeded in getting basic HTML markup. The procedure is as follows:

  • The property in question (e.g. AssemblyStep.description) has its type changed from string to string | Element which allows it to contain parsed XML
  • When rendering said property, instead of just using {thing.property} in docubricks_viewer.tsx (which works for strings, but not for Elements) use {renderDescription(thing.property)}

This is all enabled by two tricks:

  • I now parse the XML file using a DOMParser (part of the browser-supplied API) which creates a very nice representation of the XML document (though it doesn't do any validation). This makes it super-easy to extract the contents of a <description> tag as parsed XML.
  • I've written a method, renderDescription, that will accept either a string or an Element and return either a string (if the input is a string, it's passed straight through) or an array of Elements and strings (Array<string|Element> to be precise). In either case, the result can be included in the same way in a React component.

renderDescription will, if it's given an Element as argument, enumerate the children of that element. The result is an Array with exactly one element for each child node:

  • text nodes (i.e. text in the XML file) are passed through as strings so the text appears.
  • elements on the "safe" list (including a, ul, ol, li, b, i, p) are turned into React elements, preserving any attributes that might be present (so links will work), and the function is run recursively on the Element so its children are also processed.
  • <br/> is handled specially, as otherwise a React error occurs because it's not allowed to have any attributes.
  • Tags not on the safe list are rendered as strings using their textContent i.e. all XML tags are stripped out.

@rwb27
Copy link
Owner Author

rwb27 commented Oct 26, 2017

This code is in the rich_text_support branch of my fork at the moment. Shout if you want a pull request!

@rwb27
Copy link
Owner Author

rwb27 commented Oct 26, 2017

Incidentally, I don't believe this breaks anything - DocuBricks XML that includes HTML shouldn't kill the parser (though it is possible it will confuse the editor - haven't tested), and old-style DocuBricks XML will render fine in my modified viewer. At least my version of the viewer before the format change will handle XML with embedded HTML by stripping the tags and keeping the text content. It breaks links, but fails fairly gracefully.

@rwb27
Copy link
Owner Author

rwb27 commented Oct 26, 2017

Oh, and you can see it live on the OpenFlexure Microscope github site!

@rwb27
Copy link
Owner Author

rwb27 commented Dec 5, 2017

This is now added in the viewer upstream through pull request #11. No support in the editor yet, though.

@rwb27 rwb27 closed this as completed Dec 5, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant