-
Notifications
You must be signed in to change notification settings - Fork 67
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
base: develop
Are you sure you want to change the base?
[SVCS-418] Render MD Files at the Frontend #305
Conversation
There was a problem hiding this 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 librarymarkdown-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 */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
d3406b1
to
2374b64
Compare
There was a problem hiding this 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.
tests/extensions/md/test_renderer.py
Outdated
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: |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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 = { |
There was a problem hiding this comment.
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/ |
There was a problem hiding this comment.
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).
mfr/extensions/md/render.py
Outdated
|
||
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) |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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.
There was a problem hiding this 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:
-
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.
-
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<
to&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
@felliott Thanks for the review. Need to take another look since it's been a while. Hopefully later this week. |
2374b64
to
99ad810
Compare
3e72b69
to
8a29a81
Compare
8a29a81
to
edf8ae5
Compare
edf8ae5
to
9cd46de
Compare
9cd46de
to
bbbc038
Compare
There was a problem hiding this 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) |
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
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(); |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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.
- 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.
- 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.
bbbc038
to
5e4f4fd
Compare
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
'smarkdown
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).
Deployment Notes