Configure js-beautify within a react component - javascript

I am using js-beautify (the html-beautify option) to format html that is being displayed on my page, it displays but it's collapsing all the html to 1 line which is obviously not ideal because it's a pain to read. It is basically trying to format HTML as Javascript because the actual html beautify is not being applied.
I'm using it in react as below inside a specific component file for that item does anyone know how to fix this?
import htmlBeautify from 'js-beautify'
const htmlString = htmlBeautify(renderToStaticMarkup(<Component />))
export default () =>
<Example staticMarkup={htmlString}>
<Component />
</Example>
Update:
<Example/> is another component that renders out a bunch of additional stuff like a markdown description.
I'm using https://github.com/alexlande/react-style-guide to create a styleguide and passing the static html markup to staticMarkup prop to display rather than just showing the react component which in this context isn't particulary useful.

Related

How would I display a list of all Markdown posts with their HTML content with Gatsby

Recently, I've been learning Gatsby.js & GraphQL and have been working on a small project. My goal with this project is to have simply one page that displays all posts on the page, meaning no slugs, etc referencing a specific page, just having all the markdown files converted to the template I have, then all on one page. An example of what I mean is below:
Looking through the Gatsby documentation, I can see how to make a list of markdown "blogs" but they're just links that you essentially click to take you to the actual post page which isn't what I want
I tried doing something similar to that, but my problem is I can't really pass the HTML to my component because it's made up of many UI components (Material UI card components). For example, I had something like this in my index.js file that displays all my posts
const Posts = edges
.filter(edge => !!edge.node.frontmatter.question)
.map(edge => <Grid item xs={8}><PostCard key={edge.node.id} question={edge.node.frontmatter.postTitle} postContents={}/></Grid>)
Obviously the problem there is, I can't pass dangerouslySetInnerHTML into postContents. I could pass edge.node.html but then the HTML tags themselves would be showing in the content. I know there's a better way to do this, which utilizes the template file in my templates folder but I'm not exactly sure how to, I had no luck finding much regarding this on stackoverflow or the Gatsby documentation.
Would appreciate any insight on how to achieve this result
Thanks!
If you cannot pass dangerouslySetInnerHTML into postContents, then you can instead pass the edge or node itself in, and then update that component to set the inner html of a div instead.
So your PostCard would look something like:
export default function PostCard({ node }) {
return (
<div key={node.id}>
<h1>{node.frontmatter.postTitle}</h1>
<div dangerouslySetInnerHTML={{ __html: node.html }} />
</div>
);
}
And your index.js could be simplified to:
const Posts = edges
.filter(edge => !!edge.node.frontmatter.question)
.map(edge => <Grid item xs={8}><PostCard node={edge.node} /></Grid>)

Is there a way to show a React Component code into a <code> tag?

I'm building a tester page where the user sees a library component and documents its use.
Here is the component:
render = () => {
let component = (
<Slider
onSlide={this.handleSlide}
totalCount={120}
/>
);
return (
<div>
<h2>Slider Test:</h2>
{component}
<code>HOW TO PRINT COMPONENT CODE HERE?</code>
</div>
);
};
I want to show the component in use and at the end the code I've used to test it.
How can I put on screen the component code without the need to replicate it inside the tag?
Is there a way to do it directly or though an existing npm library?
You could escape the code and it should appear correctly.
You can use that library to do it escape-html npm
You should also be able to find specialized libraries to do it like this one react code view npm

Markdown rendering with React Components inside at build time

I have a very specific issue with Preact/React:
I have a .md file with some text, which uses react-router's <Link> tags inside for navigation. Like this:
## Heading
<Link to="/test">Let's go here</Link>
In my Component file, I render the Markdown and import the Link Component and pass the Link-components down, using the preact-markup component:
...
import {Link} from 'react-router-dom';
import text from './text.md';
import Markup from 'preact-markup';
export default class Comp extends Component {
render() {
return <Markup markup={text} components={{Link, HashLink}} />;
}
}
For importing the markdown, I use the #nuxtjs/markdown-it-loader, which works fine. It all works as expected, but doesn't feel clean.
I would like to be able to either import the Link components inside the markdown file, which would save me some boilerplate code for every view.
Or, even better, I would like to be able to write my markdown inside the Component itself, with the appropriate imports, and compile it all to HTML at build time.
I don't like runtime components since they need downloading and parse- and render time.

Mixing React Components with HTML Blocks

Something that's always confused me is how many React examples show everything as components. But's let's say I only need to include some simple HTML alongside my components, like:
class Homepage extends Component {
render() {
return (
<Container>
<Hero />
<Features />
<div className="copyright">Copyright Some Company Name.</div>
</Container>
);
}
}
The div element will never be more than static text.
Should the <div> be moved into a pure component? Or is it ok to simplify the Homepage component by adding plain HTML this?
Sure it's ok. all in all it's HTML in the end. React components are set of html elements when you call the render function.
One rule of thumb i follow is: create a new component when you think a new responsibility is in order.
That div is a component just like any other, except it is a "primitive" one. There should be no problem mixing the primitive components from HTML with your own custom components.

Using React with uncontrolled third-party components

I'd like to create a UI similar to JSFiddle using React:
A panel for HTML, CSS and JS
A preview panel
A single "Run" button that updates the preview
I'd like to use Microsoft's Monaco editor for the HTML, CSS and JS panels to get syntax highlight and autocomplete.
I've abstracted out a generic MonacoEditor component. My component hierarchy looks something like this:
<Root>
<div>HTML <MonacoEditor /></div>
<div>CSS <MonacoEditor /></div>
<div>JS <MonacoEditor /></div>
<button onClick={this.run}>Run</button>
<PreviewPanel />
</Root>
If I were implementing this UI in Vanilla JS, the run() method would call getValue() on each Monaco instance to extract the full text from each panel and generate the preview.
This becomes awkward with React, however, since the run() method can't call methods on instances of child components.
One workaround would be for the MonacoEditor to have an onUpdate prop which gets fired on every keystroke. The Root component could store the provisional contents of each panel for when the "Run" button was clicked. This is what I might do if each editor were a <textarea>. But it's a non-starter with Monaco. Serializing the text of the editor on every keystroke makes it unusably slow.
The only other approach I can think of is passing in a "getter setter" to the MonacoEditor component, e.g.:
class Root extends React.Component {
render() {
return (
<div>
<MonacoEditor setGetter={getter => this.getHTML=getter} />
<MonacoEditor setGetter={getter => this.getCSS=getter} />
<MonacoEditor setGetter={getter => this.getJS=getter} />
<button onClick={() => this.run()}>Run</button>
<PreviewPanel />
</div>
);
}
run() {
const html = this.getHTML();
const css = this.getCSS();
const js = this.getJS();
// ...
}
}
But this feels extremely awkward and counter to the idea of one-way databinding. Is there a better, more idiomatic approach?
You can checkout react-monaco-editor.
This will satisfy all your requirements! Especially getting value from the editor instance.
If not this, declare a function inside the editor component and use ref to call that function from other components.
Hope it helps!

Categories