kodeklubben / codeclub-viewer

A viewer to display codeclub lessons
4 stars 17 forks source link

Render HTML as react nodes #559

Open NorwegianKiwi opened 6 years ago

NorwegianKiwi commented 6 years ago

When manipulating content html and courseinfo html, the html is parsed into an AST tree, altered, and then rendered back into html, before inserting in a div with dangerouslySetInnerHtml.

Instead of this, perhaps make a function that takes the AST tree and renders into React components. See https://github.com/utatti/react-render-html/blob/master/index.js for how it can be done. (The reason we don't want to use react-render-html directly, is because we need to manipulate the AST tree between parsing the HTML and creating the React elements.) If we do this, we could stop using dangerouslySetInnerHtml, at least for lesson content and course info.

One of the things we should do with the AST tree before rendering the React elements, is to check any anchor tags <a href="...", and if they are internal links, change them to NavLink nodes.

Also, compare size of posthtml-parser (https://github.com/posthtml/posthtml-parser), which is currently used to parse html, to parse5 (https://github.com/inikulin/parse5). If parse5 is smaller, perhaps better to use it? (Unless posthtml-parser has better functionality.)

Or, perhaps we could make markdown-it render into AST trees instead of into html? Then we wouldn't need the client to parse the html every time.

NorwegianKiwi commented 6 years ago

Another thing we should do to the AST tree, is to change necessary nodes into ToggleButton, so we avoid the extra reactDOM.render inside the DOM tree inserted by dangerouslySetInnerHtml (for lesson content).

NorwegianKiwi commented 6 years ago

It might be possible to make webpack render the HTML into PostHTML AST tree, so that the client doesn't need to do this. Normally, PostHTML does the following:

HTML --(posthtml-parser)--> AST --(posthtml plugins)--> changed AST --(posthtml-render)--> changed HTML

Now, if we could only run PostHTML but turn off the last posthtml-render.

To run it in webpack, we use posthtml-loader.

If we can't make this work, perhaps create a loader (locally) that uses only posthtml-parser or parse5 and add it to webpack using loader: path.resolve('path/to/loader.js') (see https://webpack.js.org/contribute/writing-a-loader/#setup). Shouldn't be too difficult, I think.