¿Cómo renderizo Markdown desde un componente React?

6 minutos de lectura

Avatar de usuario de Capuchin
Capucho

Tengo mi documentación escrita en Markdown y me gustaría convertir esos archivos de mi código JSX (ES6+CommonJS) en componentes React. ¿Cómo puedo conseguir esto?

Por ejemplo, tengo styles.markdown y me gustaría convertirlo en un <p> etiqueta.

  • ¿Estás usando Browserify?

    – kpimov

    7 de agosto de 2015 a las 11:46

  • Sí, estoy usando browserify

    – capuchino

    7 de agosto de 2015 a las 11:53

  • ¿Estás usando Babel también? ¿Qué quieres decir con tener styles.markdown?

    – kpimov

    7 de agosto de 2015 a las 12:06

  • Sí, babel también. styles.markdown es solo un ejemplo de archivo de descuento

    – capuchino

    7 de agosto de 2015 a las 12:08

  • No estoy seguro de lo que estás tratando de hacer aquí. ¿Quiere tener algo que haga que los componentes reaccionen al descuento?

    –Mike conductor

    7 de agosto de 2015 a las 12:49

Avatar de usuario de Andre Pena
André Peña

Puedes usar React-Markdown:

const React = require('react')
const ReactDOM = require('react-dom')
const ReactMarkdown = require('react-markdown')

const input="# This is a header\n\nAnd this is a paragraph"

ReactDOM.render(<ReactMarkdown source={input} />, document.getElementById('container'))

O… Puede simplemente crear un componente React simple que envuelva una llamada a un analizador Markdown. Hay dos muy buenos para JavaScript:

Ahora, puede crear un componente como este:

var MarkdownViewer = React.createClass({
    render: function() {
        // pseudo code here, depends on the parser
        var markdown = markdown.parse(this.props.markdown);
        return <div dangerouslySetInnerHTML={{__html:markdown}} />;
    }
});

Ya había uno, pero parece que ya no se mantiene: https://github.com/tcoopman/markdown-react

Además, si necesita un React Markdown Editor, consulte: reaccionar-mde. Descargo de responsabilidad: soy el autor.

  • No estoy seguro de cuándo cambió esto, pero estaba trabajando en ello hoy y parece que React ahora requiere un objeto con un campo __html en lugar de solo una cadena (por ejemplo, dangerouslySetInnerHTML={{__html: markdown}}). Además, aunque puede que no sea relevante para la pregunta que se hace aquí, vale la pena señalar que se recomienda que la biblioteca de rebajas desinfecte la entrada para evitar XSS, si alguno de ellos es potencialmente no confiable (por ejemplo, var markdown = marked.parse(this.props.markdown, {sanitize: true});).

    – Gran abridor

    22 de diciembre de 2015 a las 4:28


  • Gracias @GrandOpener. He actualizado la respuesta en consecuencia.

    – André Peña

    6 de junio de 2017 a las 14:36

  • Es dangerouslySetInnerHTML ineficiente cuando el componente se vuelve a renderizar?

    – David Callanan

    11 de enero de 2019 a las 11:19

  • Parece que source={...} es obsoleto. En la versión actual es – <ReactMarkdown children={ ... }/>

    – mukund

    31 de julio de 2021 a las 14:50


avatar de usuario de oklas
oklas

El paquete react-markdown con Markdown El componente será una buena elección:

import React from 'react'
import Markdown from 'react-markdown'
    
var src = "# This is markdown document"
    
React.render(
  <Markdown children={src} />,
  document.getElementById('root')
)

Puede escribir en su lugar aquí-docs como este:

<Markdown>
  # Header

  * dotted lists
  * [url](/doc)
</Markdown>

Es posible especificar transformadores para link-urls e image-urls y mucho más.

  • Estoy de acuerdo con @Oklas. react-markdown es probablemente la mejor solución. Acabo de empezar a usarlo yo mismo. Sin embargo, tenga cuidado con cómo y qué comillas o tildes inversos utiliza. Si escribe en es6 y más allá, los fragmentos de código pueden causar problemas. Por ejemplo, tuve que transpilar es6 en es5 (utilicé babel transpiler en su sitio para obtener velocidad y precisión) para eliminar los errores que estaba recibiendo como “indefinido”. Solo tenga en cuenta que hay algunos desafíos aquí y allá con respecto a la sintaxis para los que debe encontrar soluciones.

    – María Campbell

    18 oct 2017 a las 11:04

  • Y este es el hilo de discusión que tuve hoy con el creador del complemento con respecto al problema: github.com/rexxars/react-markdown/issues/91 ¡rexxars fue rápido en responder y extremadamente útil!

    – María Campbell

    18 oct 2017 a las 20:17


  • Esto es bastante bueno, pero tengo algunos problemas con esto por alguna razón, las etiquetas html no funcionan cuando se pasa el descuento como cadenas, así es como se supone que funciona porque en la demostración las vi usando etiquetas html pero no parece funcionar. para mí, las cosas de descuento funcionan bien, aunque

    – Goferina

    21 de marzo de 2018 a las 19:49

  • Me encontré con una cosa: no se puede importar un .md archivo en javascript a menos que tenga el cargador adecuado, pero puede colocar fácilmente el descuento en una cadena e importarlo de esa manera.

    – cph2117

    17 de febrero de 2019 a las 15:13

Llegué un poco tarde a la fiesta, pero escribí una biblioteca competidora de las mencionadas anteriormente que tiene el beneficio adicional de no necesitar el dangerouslySetInnerHtml cortar a tajos: https://github.com/probablyup/markdown-to-jsx

  • Probé ambos react-markdown y markdown-to-jsx hoy. Larga historia corta: markdown-to-jsx es 5 veces más liviano, y fue mucho más fácil configurarlo para abrir _blank enlaces con caja fuerte noopener valores predeterminados Ver github.com/probablyup/markdown-to-jsx/issues/… (Básicamente no tuve éxito al hacer eso con react-markdown)

    – Solicitud de vado

    14 de junio de 2020 a las 15:51


Ejemplo de componente Markdown que representa html a partir de texto de descuento, la lógica de carga de datos debe implementarse en una tienda separada/componente principal/lo que sea. estoy usando marcado paquete para convertir markdown a html.

import React from 'react';
import marked from 'marked';

export default class MarkdownElement extends React.Component {
  constructor(props) {
    super(props);

    marked.setOptions({
      gfm: true,
      tables: true,
      breaks: false,
      pedantic: false,
      sanitize: true,
      smartLists: true,
      smartypants: false
    });
  }
  render() {
    const { text } = this.props,
      html = marked(text || '');

    return (<div>
      <div dangerouslySetInnerHTML={{__html: html}} />
    </div>);
  }
}

MarkdownElement.propTypes = {
  text: React.PropTypes.string.isRequired
};

MarkdownElement.defaultProps = {
  text: ''
};

Prueba algo como esto:

import fs from 'fs';
import React, { Component, PropTypes } from 'react';

class Markdown extends Component {
    constructor() {
        super(props);
        this.state = { contents: '' };
        this.componentDidMount = this.componentDidMount.bind(this);
    }

    componentDidMount() {
        const contents = fs.readFileSync(this.props.path, 'utf8');
        this.setState({ contents });
    }

    render()
        return (
            <div>
                {this.state.contents.split('\n').map((line, i) =>
                    line ? <p key={i}>{line}</p> : <br key={i} />)}
            </div>
        );
    }
}

Markdown.propTypes = { path: PropTypes.string.isRequired };

React.render(<Markdown path="./README.md" />, document.body);

O si está utilizando las funciones de ES7+:

import fs from 'fs';
import React, { Component, PropTypes } from 'react';

class Markdown extends Component {
    static propTypes = { path: PropTypes.string.isRequired };

    state = { contents: '' };

    componentDidMount = () => {
        const contents = fs.readFileSync(this.props.path, 'utf8');
        this.setState({ contents });
    };

    render() {
        return (
            <div>
                {this.state.contents.split('\n').map((line, i) =>
                    line ? <p key={i}>{line}</p> : <br key={i} />)}
            </div>
        );
    }
}

React.render(<Markdown path="./README.md" />, document.body);

Necesitarás usar el brfs transforme para poder usar fs.readFileSync si se está ejecutando en el lado del cliente.

  • sí. fs es un módulo de nodo y no funcionará en el lado del cliente (al menos que yo sepa)

    – archae0pteryx

    4 de agosto de 2017 a las 4:14

  • sí. fs es un módulo de nodo y no funcionará en el lado del cliente (al menos que yo sepa)

    – archae0pteryx

    4 de agosto de 2017 a las 4:14

¿Ha sido útil esta solución?