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

[SVCS-418] Render MD Files at the Frontend #305

Open
wants to merge 5 commits into
base: develop
Choose a base branch
from

Conversation

cslzchen
Copy link
Contributor

@cslzchen cslzchen commented Dec 7, 2017

Ticket

https://openscience.atlassian.net/browse/SVCS-418
This PR replaces: #272

Purpose

Credit goes to @AddisonSchiller 🎆 🎆 .

Currently MFR and the OSF wiki pages do not use the same flavor of markdown to render .md files. This ticket/PR fixes the inconsistency.

Changes

Before (The MFR Way)

MFR uses python's markdown library to parse the .md file in backend and send the rendered HTML content directly to the template to render..

After (The OSF Way)

MFR passes the WB download URL to the template. The frontend uses XMLHttpRequest to fetch the raw content of the MD file. markdown-it and its plugins sanitize and render the raw MD content directly on the page.

Difference between OSF and MFR

Scripts in MFR are customized and ES5-downgraded due to no package manager and no Babel.

Side Effects

No

Issues

No

QA Notes

Try several MD files and compare the rendering with OSF Wiki. They should looks the same (mostly).

  • @cslzchen Create a staging OSF folder containing a variety of MD files for tests

Deployment Notes

Copy link
Contributor Author

@cslzchen cslzchen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For Myself:

  • Before this PR, MFR relies on the python library markdown. After this PR, MFR delegates the rendering to front-end using javascript library markdown-it (similar to OSF Wiki). However, please elaborate more on the difference between OSF Wiki and MFR Markdown
  • Add comment in each external javascript file: where is the original copy? what is the version? what is our customization? ...
  • Fix style (using eslint and learn from our front-end team)
  • Make sure that the scripts are ES5 compatible. MFR is different from OSF and Ember since the scripts in our code base go directly to the server.

@@ -0,0 +1,2 @@
/*! markdown-it-sanitizer 0.4.3 https://github.com/svbergerem/markdown-it-sanitizer @license MIT */
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@cslzchen cslzchen force-pushed the feature/svcs-418-improve-md branch 6 times, most recently from d3406b1 to 2374b64 Compare December 8, 2017 19:23
Copy link
Contributor Author

@cslzchen cslzchen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ready for Phase 2 Review. @felliott (But let me update the PR description first 🎆 )

At lease one of the following is necessary:

  • Comprehensive test .md files for QA and Dev testing
  • Comprehensive python tests, which is more challenging since rendering is performed by javascript.

The travis error is unrelated. Somehow the test.zip contains a .DS_Store for .zip renderer. A separate PR to fix this is recommended.

in_body = 'The rain---not the reign---in\nSpain.\n\n<script>\nalert("Hello world");\n</script>'
assert in_body in body

# TODO: it is hard to test since rendering is performed by front-end javascript, if possible test the following:
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is hard to test front-end based rending for .md and there a lot to test. I will try to add more tests before/during phase 2 review if we think it is necessary.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure how relevant this is, but I mostly just tried to test bleach quickly here. It may be worth while to make sure proper tags are being bleached, and javascript would get escaped out etc. The above is already testing for that a little.
Might be worth a parameterized test to test all the BLEACH_WHITELIST tags or whatever that setting got called.

.eslintrc.js Outdated
@@ -0,0 +1,18 @@
module.exports = {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a basic configuration for eslint.

.gitignore Outdated
@@ -11,19 +11,29 @@ Thumbs.db
*.swp
*~

# Node Modules
######################
/node_modules/
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update .gitignore to exclude ./node_modules/ (here) and ./src/ (below).


def render(self):
"""Render a markdown file to html."""
with open(self.file_path, 'r') as fp:
body = markdown.markdown(fp.read(), extensions=[EscapeHtml()])
body = bleach.clean(fp.read(), **md_settings.BLEACH_WHITELIST)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although MFR uses bleach the same way OSF does, the library is not exactly the same due to python version difference.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if it got noted somewhere else, but more specifically it causes problems with unclosed tags.

Mark down is great!
<p> okay </p

other stuff
more stuff

will usually just cut off the last 2 lines and end at at the 'okay' in a completed <p> tag

Copy link
Contributor Author

@cslzchen cslzchen Dec 15, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. My test didn't have the extra lines which made me believe that python35's bleach closes unclosed tags correctly. I will test this again. Thanks for the follow up @AddisonSchiller

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't remember the exact behavior, but I do recall it working correctly sometimes with unclosed tags, and other times displaying the above behavior. May need a bit more investigation to figure out the full extent of it. Bleach also had some github issues that explained the behavior as well. They may be linked on an old comment somewhere, or on the old PR. May be worth checking those out.

@cslzchen cslzchen changed the title [SVCS-418] [WIP] Improve md rendering [SVCS-418] Improve md rendering Dec 8, 2017
Copy link
Member

@felliott felliott left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @cslzchen,

Two things for this pass:

  1. The test_zip failure is because bleach pulls in html5lib, which wasn't installed before. BeautifulSoup (used in test_zip) uses the python html parser by default, but will switch to html5lib if available. The test_zip test should be updated to explicitly state which parser it's using. I'm okay with that happening as part of this ticket.

  2. I tested this using the README.md file in the PR. This PR does not handle that file very well. It both sanitizes the <PLUGIN_NAME> strings and adds closing tags for them to the end of the file (</plugin_name>). Then something (maybe the markdown-it sanitizer) is doubly-encoding the &lt; to &amp;lt;. Is there a way we can avoid this? Can we load the markdown dynamically and only pass it through the markdown-it sanitizer?

Cheers,
@felliott

@cslzchen
Copy link
Contributor Author

cslzchen commented Mar 5, 2018

@felliott Thanks for the review. Need to take another look since it's been a while. Hopefully later this week.

@cslzchen cslzchen force-pushed the feature/svcs-418-improve-md branch from 2374b64 to 99ad810 Compare March 16, 2018 21:32
@cslzchen cslzchen force-pushed the feature/svcs-418-improve-md branch 2 times, most recently from 3e72b69 to 8a29a81 Compare April 17, 2018 16:31
@cslzchen cslzchen force-pushed the feature/svcs-418-improve-md branch from 8a29a81 to edf8ae5 Compare May 2, 2018 22:42
@coveralls
Copy link

coveralls commented May 2, 2018

Coverage Status

Coverage decreased (-0.1%) to 70.907% when pulling 5e4f4fd on cslzchen:feature/svcs-418-improve-md into 7304d3b on CenterForOpenScience:develop.

@cslzchen cslzchen force-pushed the feature/svcs-418-improve-md branch from edf8ae5 to 9cd46de Compare May 3, 2018 04:26
@cslzchen cslzchen changed the title [SVCS-418] Improve md rendering [SVCS-418] Render MD files at the Frontend May 3, 2018
@cslzchen cslzchen force-pushed the feature/svcs-418-improve-md branch from 9cd46de to bbbc038 Compare May 3, 2018 14:07
Copy link
Contributor Author

@cslzchen cslzchen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Finally, ready for review once more! 🎆

with open(self.file_path, 'r') as fp:
body = markdown.markdown(fp.read(), extensions=[EscapeHtml()])
return self.TEMPLATE.render(base=self.assets_url, body=body)
return self.TEMPLATE.render(base=self.assets_url, url=self.metadata.download_url)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MD renderer is now of type direct-to-wb instead of through-renderer. Only pass the WB download URL to the template.

<script>

## How to load ``markdown-it``: https://github.com/markdown-it/markdown-it#simple
var MarkdownIt = window.markdownit;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use window.<LIBRARIES> to load the libraries which have already been wrapped with root.<LIBRARIES> due to MFR lacking a package manager.

wb_request.onload = function () {
document.getElementById("mdViewer").innerHTML = markdown.render(wb_request.response);
## Force the host to resize
window.pymChild.sendHeight();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

iframe has a min height of 150 pixels, which is the height before its innerHTML is updated. Without this line, it doesn't resize to proper height unless there is a certain user action (scrolling, clicking, resizing, etc.) on the page.


def test_render_md(self, mock_renderer):
body = mock_renderer.render()
assert mock_renderer.metadata.download_url in body
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only thing that needs testing is that the download URL are correctly passed to and parsed by the template.

@cslzchen cslzchen changed the title [SVCS-418] Render MD files at the Frontend [SVCS-418] Render MD Files at the Frontend May 3, 2018
cslzchen added 2 commits June 19, 2018 09:51
- MFR uses the same markdown-it.js and its plugins
  as OSF for rendering MD. However, due to lack of
  package managing and Babel, all full scripts are
  manually eslinted and babeled if necessary. .min
  scripts are kept intact.
- Instead of sending the HTML rendered by python
  markdown, MD renderer passes the WB download URL
  directly to the template.
- Direct-to-wb replaces through-renderer as the
  new dispatch type.
cslzchen added 3 commits June 19, 2018 09:51
- MFR frontend makes XHR to fetch the raw content
  directly from WB with CORS enforced. Markdownit
  and its plugins sanitize and render the content
  before updating the MFR viewer.
Empty __init__.py and unused fixtures/files are
removed. The new test only verifies the download
url. The acutual render process is done in the
browser.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants