Gatsby: Usando componentes de React en la fuente de Markdown

Creado en 5 jun. 2016  ·  112Comentarios  ·  Fuente: gatsbyjs/gatsby

¿Existe una manera fácil de usar los componentes de React en mi fuente de Markdown? ¿Algo como reactdown ?

question or discussion

Comentario más útil

Así que he estado tratando de pensar en una forma limpia de mezclar React y Markdown prácticamente desde siempre. O al menos desde que empecé a trabajar en Gatsby.

Y por fin creo que tengo una idea que podría funcionar.

Usaríamos la misma regla para diferenciar entre elementos HTML normales y componentes React como hace JSX, es decir, React está en mayúsculas.

Entonces puede incluir componentes de React directamente en su Markdown, por ejemplo

# Hi folks

I'm writing some markdown about speaker <Person id="Paul Ryan">Paul Ryan</Person> who's the speaker of the house and other stuff.

<InteractiveComponent invertedColors={true} allTheProps={true} />

Entonces esto se analizaría en un AST algo como:

[
  [{ raw: true, value: "<h1>Hi Folks</h1>" }],
  [
    { raw: true, value: "<p>I'm writing some markdown about speaker " },
    {
      raw: false,
      value: {
        name: "Person",
        props: { id: "Paul Ryan", children: "Paul Ryan" }
      }
    },
    { raw: true, value: " who's the speaker of the house and other stuff.</p>" }
  ],
  [
    {
      raw: false,
      value: {
        name: "InteractiveComponent",
        props: { invertedColors: true, allTheProps: true }
      }
    }
  ]
];

Y luego, en su componente, en lugar de representar directamente (estilo de peligro) el HTML, lo pasaría a una función auxiliar con un mapeo para cada componente de React algo como:

import React from "react";
import renderHtmlReact from "gatsby-render-html-react";
import Person from "../components/Person";
import InteractiveComponent from "../components/InteractiveComponent";

export default ({ data }) => (
  <div>
    {renderHtmlReact({
      ast: data.markdownRemark.ast,
      componentMap: { Person, InteractiveComponent }
    })}
  </div>
);

// Your query goes down here

Necesitaríamos hacer algunos prototipos para asegurarnos de que esto funcione con Remark, pero estoy bastante seguro de que el "Html" de React se pasará intacto. Así que solo necesitaríamos un analizador para dividir el HTML y convertir las partes de React JSX en datos, así como la biblioteca de interfaz para representar el "AST" resultante.

Pensamientos?

Todos 112 comentarios

Esa es una gran idea. Estaría dispuesto a trabajar si aún no está disponible.

Soy el desarrollador de reactdown. Sería increíble ver a Reactiondown trabajando con Gatsby. Envíeme un ping si tiene preguntas o necesita ayuda para integrarlo.

👍 esta es una solicitud común, por lo que sería genial tener algo que funcione y que esté ampliamente disponible.

Configuré un repositorio de ejemplos rápido y sucio de cómo hacer que reactdown funcione con gatsby. Es bueno tener en cuenta que debajo del capó, Gatsby es solo una envoltura muy fácil de usar en la parte superior del paquete web, por lo que toda la potencia todavía está ahí para hacer casi cualquier cosa.

https://github.com/benstepp/gatsby-reactdown

Gracias, lo intentaré y te dejaré saber cómo te fue.

¡Oh genial! Buen Ben. Eso es mucho más simple de configurar de lo que había estado imaginando
jaja. Buen trabajo, Andrey.

El martes, 7 de junio de 2016 a las 10:31 p.m. Jo Meenen [email protected] escribió:

Gracias, lo intentaré y te dejaré saber cómo te fue.

-
Estás recibiendo esto porque comentaste.

Responda a este correo electrónico directamente, véalo en GitHub
https://github.com/gatsbyjs/gatsby/issues/312#issuecomment -224492088,
o silenciar el hilo
https://github.com/notifications/unsubscribe/AAEVh-2doZe_FXFMBxYTJ5FAVqo4XqxNks5qJlO6gaJpZM4Iubim
.

@benstepp ¡agradable! Esto parece bastante sencillo cuando se usan archivos de Markdown a través de un contenedor, pero ¿funcionaría esto también al importar el archivo de Markdown para usar dentro de un componente de React?

Editar: parece que debería funcionar de inmediato, pero de alguna manera el componente React en el que se transforma el archivo md no genera nada ...

He estado pensando en un enfoque diferente que abre la nueva capa GraphQL (# 420). Abrí un problema preguntando al respecto en el repositorio de mdash https://github.com/wooorm/mdast/issues/13

¡Eso sería genial! Sin embargo, sentí que estaba tan cerca de Reactdown ... Los archivos de markdown se transforman correctamente en componentes de React mediante el paquete web (al menos así lo parece), pero solo me da componentes vacíos cuando los uso en mi código.

¿@SachaG tiene un repositorio en algún lugar al que pueda echar un vistazo?

Vaya, realmente raro. Estaba intentando crear una reproducción del problema, ¡y ahora funciona! Ni siquiera estoy seguro de qué cambió ... No puedo quejarme, supongo :)

Los dioses de React bajaron en un carro dorado, ¡y he aquí! el código funcionó

@SachaG Recuerdo que hubo algunos problemas con la forma en que reactdown hace referencia a su tiempo de ejecución. De todos modos, si encuentras algunos problemas, sería plano de ayuda.

¡Hola! ¿Ha habido alguna actualización reciente de esto? ¿Cuál es el método recomendado para usar componentes react en markdown? ¿Hay algún ejemplo que pueda seguir? ¡Gracias!

Todavía no :-( Tengo un buen plan sobre cómo hacerlo; básicamente, compile el archivo de rebajas en un archivo de componentes de React donde maneja la importación correcta de todos los componentes de React a los que se hace referencia, pero aún no he necesitado compilarlos. ¡empieza a trabajar en ello si lo necesitas!

@KyleAMathews ¿Quiere decir que debería ejecutar un script de conversión en mi archivo de rebajas y luego agregar manualmente los otros componentes de reacción que necesito al archivo de salida producido por el paso de conversión? Una vez hecho esto, ¿la compilación final?

Idealmente, esto sería un complemento para Gatsby v1 que haría estos pasos
automáticamente.

El martes 2 de mayo de 2017 a las 12:50 p.m., Piyush Singh [email protected] escribió:

@KyleAMathews https://github.com/KyleAMathews ¿Quieres decir que debería correr?
un script de conversión en mi archivo de rebajas y luego agregue el otro react
componentes que necesito para el archivo de salida producido por el paso de conversión? Una vez
esto se hace entonces hacer la construcción final?

-
Estás recibiendo esto porque te mencionaron.

Responda a este correo electrónico directamente, véalo en GitHub
https://github.com/gatsbyjs/gatsby/issues/312#issuecomment-298741837 ,
o silenciar el hilo
https://github.com/notifications/unsubscribe-auth/AAEVh4riB8uXgeRUybcR6OxsC1EAKnkKks5r14kPgaJpZM4Iubim
.

Un simple ejemplo de lo que quiero decir.

Imagine que tiene un archivo de rebajas en /my-blog/index.md que se parece a lo siguiente:

---
title: "hi folks"
---

# This is my broomstick

Yo yo foo

<SweetComponent props="super cool" />

El cuerpo podría convertirse en un componente de reacción que se ejecutaría a través de webpack / babel / etc. como normal.

import React from 'react'
import SweetComponent from 'auto-resolve-this-somehow'

class MarkdownBody extends React.Component {
  render () {
    return (
      <div>
        <h1>This is my broomstick</h1>
        <p>Yo yo foo</p>
        <Sweet Component props="super cool" />
      </div>
    )
  }
}

La parte del truco es cómo integrar esto con el sistema graphql de Gatsby. Idealmente, podría simplemente consultar la versión del "componente" de un archivo de rebajas similar a cómo puede consultar el HTML hoy.

De todos modos, ese es un breve bosquejo de lo que he pensado.

@KyleAMathews gracias, creo que ahora entiendo la idea.

Mi objetivo es poder escribir contenido como este que aproveche las visualizaciones de MathJax, D3.js y también podría incorporar componentes de animación Three.js dentro de la fuente de rebajas.

Si ve la fuente html aquí, la página usa jQuery para algunos de los controles deslizantes, aunque imagino que podría haber mejores formas de hacer cosas de jQuery con componentes de React.

Por lo que he recopilado hasta ahora, imagino que producir tal contenido con el marco de Gatsby se puede lograr de una manera mucho más ordenada y estructurada, ¿verdad?

Soy nuevo en el desarrollo web, pero estoy haciendo todo lo posible por aprender cómo funciona el sistema Gatsby para poder contribuir a lograr este tipo de objetivos ...

@KyleAMathews , he estado pensando en su solución propuesta ...

¿Crees que algo como markdown-it-jsx podría usarse o mejorarse para realizar la conversión a la estructura de componente MD JS deseada?

Para resolver auto-resolve-this-somehow part, quizás un segundo analizador podría escanear el archivo del componente MD JS para buscar JSX que coincida con los de una lista de registro de componentes (que podría ser un archivo de texto simple o una búsqueda de archivos en el directorio donde todos los componentes se almacenarán) y luego agregar la línea de importación relevante en la parte superior del archivo?

Voy a empezar a trabajar en esto para que cualquier comentario sea fantástico.

Solo una nota, hay otro proyecto que está haciendo esto, tal vez sea útil como referencia: react-styleguidist . Ejemplo de archivo de rebajas

Habilitar componentes en rebajas me recuerda esta obra maestra de Bret Victor.

UPD: y un ejemplo más: mdxc

Y otro http://thejameskyle.com/react-markings.html

Una solución es usar react-jsx-parser .
En howtographql.com lo estamos usando en producción: https://github.com/howtographql/howtographql/blob/master/src/components/Tutorials/Markdown.tsx#L182

Una desventaja: por supuesto, es más lento que usar dangerouslySetInnerHTML , porque

  1. Analiza el HTML
  2. Construye un árbol dom virtual
  3. Renderiza el árbol virtual con React

Una forma de acelerar esto sería no enviar el html sin procesar con la consulta graphql, sino enviar un formato que están usando los documentos de Inferno.js, como se describe aquí .

Como actualmente no puedo encontrar el tiempo para hacer este último paso de optimización, cualquiera que esté interesado en él podría seguir este enfoque.

Eso significaría

  1. Construya tipos de GraphQL adecuados, eso no debería ser un problema ya que los tipos de GraphQL pueden ser recursivos y representar un árbol
  2. Una vez finalizado el negocio de análisis de rebajas remark , genere un formato jsx serializado.
  3. En React deserialice este formato.

Otra opción que he estado mirando es https://github.com/mapbox/jsxtreme-markdown

Podríamos usar un patrón similar. Simplemente convierta markdown a componentes JSX. Utilice delimitadores personalizados para agregar JavaScript y JSX. Podríamos usar nuestra configuración de Remark existente sin problemas. Y no habría mucha penalización en el rendimiento, ya que solo serían páginas de React normales.

También está https://github.com/cerebral/marksy , que utilicé recientemente con buenos resultados.

¿Existe un enfoque recomendado para esto en el contexto de Gatsby o aún está por decidirse?

Hola, ¿alguna recomendación para incluir componentes aduaneros en nuestros archivos de rebajas de gatsby?

Una opción más en la colección https://idyll-lang.github.io/

Parece que Marky funciona muy bien para ese caso de uso

ya que devuelve un árbol de elementos de reacción, me pregunto cómo podría integrar eso en un complemento de gatsby.

@KyleAMathews @revolunet ¿Qué opinas sobre el registro de los componentes que necesitamos usar como elementos personalizados, luego podemos simplemente incluirlos en la publicación del blog y dejar el resto del trabajo para que lo haga el navegador?

Esto eliminaría cualquier necesidad de analizar markdown como un árbol de reacción y mantener nuestra aplicación en funcionamiento, sin embargo, no sé si habrá un costo de rendimiento, para hacer ReactDOM.render cada vez que necesitemos agregar un nuevo componentes personalizados, pero aún así nos daría una manera genial de agregar funcionalidad dinámica a las publicaciones del blog.

@abdulhannanali Registrar los componentes disponibles en la rebaja es una buena idea, pero el tema de los elementos personalizados no suena muy amigable para el servidor :)

Así que he estado tratando de pensar en una forma limpia de mezclar React y Markdown prácticamente desde siempre. O al menos desde que empecé a trabajar en Gatsby.

Y por fin creo que tengo una idea que podría funcionar.

Usaríamos la misma regla para diferenciar entre elementos HTML normales y componentes React como hace JSX, es decir, React está en mayúsculas.

Entonces puede incluir componentes de React directamente en su Markdown, por ejemplo

# Hi folks

I'm writing some markdown about speaker <Person id="Paul Ryan">Paul Ryan</Person> who's the speaker of the house and other stuff.

<InteractiveComponent invertedColors={true} allTheProps={true} />

Entonces esto se analizaría en un AST algo como:

[
  [{ raw: true, value: "<h1>Hi Folks</h1>" }],
  [
    { raw: true, value: "<p>I'm writing some markdown about speaker " },
    {
      raw: false,
      value: {
        name: "Person",
        props: { id: "Paul Ryan", children: "Paul Ryan" }
      }
    },
    { raw: true, value: " who's the speaker of the house and other stuff.</p>" }
  ],
  [
    {
      raw: false,
      value: {
        name: "InteractiveComponent",
        props: { invertedColors: true, allTheProps: true }
      }
    }
  ]
];

Y luego, en su componente, en lugar de representar directamente (estilo de peligro) el HTML, lo pasaría a una función auxiliar con un mapeo para cada componente de React algo como:

import React from "react";
import renderHtmlReact from "gatsby-render-html-react";
import Person from "../components/Person";
import InteractiveComponent from "../components/InteractiveComponent";

export default ({ data }) => (
  <div>
    {renderHtmlReact({
      ast: data.markdownRemark.ast,
      componentMap: { Person, InteractiveComponent }
    })}
  </div>
);

// Your query goes down here

Necesitaríamos hacer algunos prototipos para asegurarnos de que esto funcione con Remark, pero estoy bastante seguro de que el "Html" de React se pasará intacto. Así que solo necesitaríamos un analizador para dividir el HTML y convertir las partes de React JSX en datos, así como la biblioteca de interfaz para representar el "AST" resultante.

Pensamientos?

Y luego, en su componente, en lugar de representar directamente (estilo de peligro) el HTML, lo pasaría a una función auxiliar con un mapeo para cada componente de React algo como:
[…]
Pensamientos?

Esto es algo que también hemos estado haciendo (muy simplificado, no realmente seguro y solo diseñado para etiquetas específicas). Nuestro caso de uso fue diseñar / diseñar un documento JSON:

<IconGrid src="sensors.json" />

Esto fue realmente útil para evitar contenido duplicado y estamos contemplando el uso de un mecanismo similar para componentes de documentación API reutilizables.

Algo de lo que carece esta solución, que tampoco resolvimos, es el uso de rebajas en las propiedades de los componentes. Para que algo como esto sea posible:

<Api method="post" description="
An API which uses **markdown**.

And having multi line parameters would be helpful as well.
" />

Después de probar toneladas de cosas en este espacio por un tiempo, ahora estoy convencido de que sí, realmente debe resolverse en el nivel de rebajas. Lo que significa que el sabor de la rebaja realmente necesita comprender jsx / react. El problema es realmente la interpolación de javascript que jsx admite y el markdown se bloquea. Jsxtreme-markdown se acerca y soluciona esto procesándolos primero y luego usando markdown para analizar el resto. Otro enfoque es apoyarse en la capacidad natural de los analizadores MD para manejar html y, por lo tanto, jsx sencillo (Marcado, por ejemplo, manejará elementos en mayúsculas) pero rápidamente se encontrará con limitaciones molestas al estar atascado en accesorios de solo cadena y sin rebajas anidadas (por ejemplo, Markdown dentro , props.children). El otro problema es que la hidratación del cliente se vuelve molesta porque necesitas un tiempo de ejecución (y generalmente uno bastante grande) para convertir una cadena en elementos de reacción, lo que no es ideal para el enfoque de Gatsby en un tiempo rápido de interacción y rendimiento.

Creo que la forma más prometedora a seguir es un enfoque basado en ast, pero para eso realmente necesita una variante de reducción de velocidad que sea lo suficientemente diferente de las existentes para ser un proyecto considerable

¡Solo arrojo mis 2 centavos!

Antes de saber que gatsby existía (hace 2 años), intenté hacer un generador de sitios estáticos de reacción que se comportara de manera similar a jekyll ( rovr ). Quería mezclar markdown, react y html en mis archivos md.

Opté por usar una expresión regular para encontrar <CapitalizedComponents/> dentro del contenido de rebajas y funcionó bastante bien, excepto que tenía algunos casos extremos. En ese momento, estaba usando marcado que tenía algunos efectos secundarios extraños en su análisis de html.

Además, mi expresión regular simplista no permitía etiquetas finales de componentes y, por lo tanto, no tenía hijos ... así que esto no funcionó:

<Component>
   <Child/>
</Component>

De todos modos, ¡estoy muy emocionado de que Gatsby apoye esto! Estoy en el proceso de convertir mi sitio jekyll a gatsby y estoy casi terminado. Mi siguiente tarea es averiguar cómo cambiar mi jekyll incluye dentro de las publicaciones del blog de md a componentes en mi versión de gatsby.

@jquense está de acuerdo en que no admitir JS en markdown sería una limitación. Pero por el lado positivo, esto encajaría muy bien dentro de nuestra estructura existente. La biblioteca en tiempo de ejecución sería bastante simple, simplemente recorrer de forma recursiva los elementos de creación de AST. También podríamos configurarlo para que analice automáticamente cualquier texto secundario de los componentes como rebaja, de modo que los componentes para esto sean solo dangerouslySetInnerHTML en props.children .

No es una solución al 100%, pero funcionaría para muchas configuraciones. Tampoco soy un gran admirador de la idea de escribir JS dentro de markdown. Pierde todo el soporte de herramientas de esa manera.

@jakedeichert sí, la expresión regular simple solo llega hasta cierto punto. ¡Genial, tienes algo similar funcionando! Eso valida el concepto. Querríamos utilizar un analizador JS que entienda JSX para extraer información estructurada. De esta manera podríamos admitir componentes anidados.

@KyleAMathews ¿Cuál es el progreso de lo que ha propuesto?

Algunos pensamientos sobre esto:

  1. Tengo un ejemplo de trabajo que usa el comentario para transformar el descuento que contiene componentes de reacción arbitrarios tmp-comment-jsx . Usé remark-html y hast-util-to-html como proyectos base.
    Aquí hay un ejemplo de uso + salida: ejemplo
    Puedo proporcionar más información sobre cómo funciona si está interesado.
  2. MapBox creó un paquete comment-react que transforma markdown en elementos de reacción mediante el uso de comentario. Puede que sea necesario un poco de trabajo adaptar el paquete para que acepte elementos de reacción personalizados.

Nadie ha comenzado a trabajar en ello afaik.

El problema con esos dos enfoques es que no funcionan con el sistema de datos basado en GraphQL de Gatsby, ya que las consultas GraphQL solo pueden devolver datos que no ejecutan código. comment-react, por ejemplo, realiza la conversión markdown => html en el cliente para evitar esto, que es más caro que ideal.

Entonces, para trabajar con GraphQL, necesita un tiempo de ejecución de cliente para crear los componentes de React. Mi propuesta surgió de trabajar en un diseño que permitiría el menor tiempo de ejecución posible.

Creo que lo entiendo ahora. Entonces, en su opinión, lo que se necesita son dos piezas de código:

  1. markdown -> listo para usar HAST que admite componentes react. (¿Este código debería ejecutarse en tiempo de compilación?)
  2. react enabled HAST -> react element (Esto debería ejecutarse en el lado del cliente con un tiempo de ejecución mínimo / trivial)

¿Lo estoy haciendo bien? ¿Me estoy perdiendo de algo?

¡Sip!

Me encontré con otro proyecto en este espacio: tiene algunas ideas interesantes https://github.com/luiscarli/md-to-react

Hola,

Voy a intentarlo de nuevo. Tengo un ejemplo funcional de la primera parte que crea el HAST aquí comment-custom-element-to-hast . Todavía necesita admitir el uso de markdown como elementos secundarios y tal vez un cargador de paquetes web que lo use.

@KyleAMathews ¿Crees que el enfoque coincide con tu punto de vista?

En cuanto a la segunda parte, podemos usar syntax-tree / hast-to-hyperscript . Aquí hay un ejemplo de uso wooorm / comment-vdom .

@ fazouane-marouane ¡genial! Sí, de un vistazo rápido parece muy cercano. ¡Buen trabajo!

Sin embargo, no queremos usar hast-to-hyperscript en la interfaz, ya que tiene un montón de dependencias y queremos que el tiempo de ejecución sea lo más ligero posible, por ejemplo, simplemente recurrir a través del AST creando elementos React. Así que mueva tanto en la segunda biblioteca a su módulo.

@KyleAMathews ¡ Eso es genial entonces! Intentaré realizar los pasos restantes en los próximos días. Esperamos que esto nos acerque un paso más a una solución práctica.

Hola @ fazouane-marouane & @KyleAMathews , Leí su discusión e implementé versiones "simples" de las diversas partes que describió aquí en esta aplicación en la que estoy trabajando.

Las partes interesantes son las que usan el código @ fazouane-marouane en forma de un complemento de gatsby aquí y la parte donde representamos HAST aquí . También puede ser interesante ver cómo se recupera el HAST gracias a GraphQL.

Tenga en cuenta que en el momento en que escribo este comentario está lejos de ser perfecto, optimizado y limpio.

EDITAR: mi componente renderHAST está muy inspirado por la forma en que fenómica se ocupa de la reducción de la representación en el lado del cliente: https://github.com/phenomic/phenomic/blob/master/packages/plugin-renderer-react/src /components/BodyRenderer.js

@pbellon ¡ Gracias por participar! Esto les ahorrará a todos mucho tiempo. El código parece estar haciendo lo necesario para el resto de los pasos. Lo intentaré más tarde esta noche.

Una cosa que necesito depurar es la forma de manejar los elementos secundarios de los componentes.
Ahora mismo, si configuro escribir en la rebaja This is a test <MyComponent>let's see how children are handled</MyComponent> la propiedad MyComponent children se establecerá en [0, null] .

Pero no estoy seguro de si proviene del analizador o de la forma en que hidrato HAST.

@pbellon viene del analizador. Es un analizador minimalista para crear un prototipo de toda esta reacción en la reducción. Definitivamente necesitará algunas correcciones para poder usarse en todos los casos. No dude en enviar un problema si encuentra más ejemplos. Ayudará a hacer una buena base de prueba de todos modos.

@ fazouane-marouane Ya veo. Intentaré por mi parte jugar con tu código para ver si puedo implementar esta función (y hacer un PR si logro hacerlo) pero no parece una modificación trivial 😮
He creado un problema en su repositorio aquí

Participando con mis $ 0.02. Como parte del desarrollo de GitDocs , necesitábamos una forma de permitir a los usuarios incrustar JSX dentro de archivos de rebajas. Esto es lo que tengo hasta ahora.

Análisis de Markdown

El procesamiento de rebajas utiliza unificado , comentario y reenvío . Se bifurcó un tokenizador personalizado del HTML del bloque de comentarios con una expresión regular adicional para detectar JSX. Este tokenizador permite volver a activar la detección de bloques JSX como raw para su posterior procesamiento.

Escribí un complemento de rehype personalizado que funciona de manera similar a rehype-raw pero que admite JSX y alguna evaluación de expresión básica. El complemento encuentra raw nodos y determina si son JSX al intentar analizar el bloque usando acorn-jsx . Si el análisis es exitoso, el JSX AST producido por Acorn se convierte en HAST.

JSX compatible

Hasta ahora puedo convertir los siguientes bits de JSX (casos de ejemplo tomados del conjunto de pruebas)

<Test>
  <Test2></Test2>
</Test>
<Test>some text</Test>
<Test attr={{ prop: 400 }} />

Expresiones

Se admite la evaluación de expresión de tiempo de compilación

<Test attr={1 + 2}/>

El nodo HAST creado tendrá la propiedad 'attr' establecida en 3 .

Expresiones de matriz

El uso de Array.prototype.map() está permitido en propiedades:

<Test attr={ [1,2,3].map(x => 2 * x) } />

Incluso puede mapear sobre una matriz y crear hijos JSX

<Test>{ [1,2,3].map(x => (<Test2>{x}</Test2>)) }</Test>

se traducirá a HAST como el equivalente de

<Test>
  <Test2>1</Test2>
  <Test2>2</Test2>
  <Test2>3</Test2>
</Test>

Limitaciones

El soporte de expresiones es bastante limitado y no se ha revisado la seguridad. El código no usa eval y acceder a cosas como window no debería ser posible, pero no puedo ofrecer ninguna garantía.

Hice un experimento en esta área donde puedes usar completamente los complementos de comentarios de gatsby como de costumbre. Pasas el html de graphql a un cargador de paquetes web que produce el código react.js. Desafortunadamente, tiene varios problemas y rompe las compilaciones de producción única.

          createPage({
            path: edge.node.fields.slug,
            component: getCdResolve(blogPost, edge.node.fileAbsolutePath, {
              html: edge.node.html,
              site: result.data.site,
            }),
            context: {
              slug: edge.node.fields.slug,
            },
          })

Donde cdResolve devuelve una cadena como !!cd-resolve-loader!foo.md . A Gatsby no le gusta eso. Al menos funciona en el servidor de desarrollo.

El resto del código está aquí .

El resultado de la compilación es un componente simple con un conjunto de nodos estáticos para niños.

var h = require('react').createElement;
var n1 = h('div', { key: 1, dangerouslySetInnerHTML: { __html: '<h1>Hello</h1>' } });
var n2 = h(CustomComponent, { key: 2, foo: 1 });

module.exports = () => h('div', null, [n1, n2]);

¡Eh interesante!

Desafortunadamente, esto también rompería la recarga en caliente de la rebaja en desarrollo, por lo que puedo decir.

Sí, ese fue otro problema. Creo que si los problemas se resolvieran de alguna manera, sería uno de los mejores resultados finales, en cuanto al tamaño del paquete y el tiempo para interactuar. Por supuesto, está bastante lejos de ser una solución funcional. ¿Algún consejo sobre cómo obtener la compilación de archivos JS después de que el comentario funcione?

@brigand Creo que la solución más fácil es la que describí en un comentario anterior https://github.com/gatsbyjs/gatsby/issues/312#issuecomment -336681894

@KyleAMathews Para la solución que propuso, ahora sabemos cómo transformar el markdown que contiene jsx en html AST usando commentjs. Hemos resuelto el último error de bloqueo. Todo lo que necesitamos ahora es crear el código que pueda transformar este AST en un componente de reacción y enviarlo a npm. Tendré algo de tiempo libre para hacer esto a finales de la próxima semana.

No dudes en presentarte en la puerta de mi casa con un bate de béisbol si no presiono algo para entonces 😅.

@ r24y consiguió esto funcionando !!! Consulte su PR https://github.com/gatsbyjs/gatsby/pull/3732 y la página de ejemplo en el sitio de ejemplo de using-comment.

https://using-remark.gatsbyjs.org/custom-components/

Entonces, informando mi progreso aquí. Tuve tiempo para terminar el segundo paso.

Con todo, tenemos dos paquetes:
El análisis en HAST: @ dumpster / comment-custom-element-to-hast
La representación trivial en el componente de reacción: @ dumpster / hast-react-renderer

@pbellon propuso un complemento de Gatsby aquí.

Esta canalización debería ser más permisiva que rehype. Si mi memoria no me falla, rehype usa parser5 que no acepta <Note value="my content" /> y no puedo recordar si acepta cuerpos para elementos personalizados.

@KyleAMathews No estoy seguro de cuál es el siguiente paso a partir de aquí.

@ fazouane-marouane increíble !!!

Creo que los próximos pasos serían agregar un sitio de ejemplo al repositorio para que también podamos mostrar su trabajo; luego, necesitamos obtener una página de documentos en gatsbyjs.org para hablar sobre las diferentes opciones y compensaciones que tienen.

Dulce Gracias por las aclaraciones.

Intentaré tener algo para la próxima semana o la semana siguiente (comenzando en un nuevo trabajo este lunes 😅).

Interviniendo. Después de leer https://using-remark.gatsbyjs.org/custom-components/ y probarlo, hice un pequeño paquete llamado gatsby-comment-component para evitar las advertencias validateDOMNesting que obtienes si tu componente está dentro de tu markdown contiene elementos a nivel de bloque (div ...). Los componentes personalizados se envuelven de forma predeterminada en un párrafo, mientras que con este paquete se envuelven en un div.
Es bastante fácil de usar

//In your gatsby-config.js
plugins: [
  {
    resolve: "gatsby-transformer-remark",
    options: {
      plugins: [
        {
          resolve: "gatsby-remark-component",
          options: { components: ["my-component", "other-component"] }
        }
      ]
    }
  }
]

Espero que esto le sea útil a alguien.

@Hebilicious gracias por el complemento; sí, me di cuenta de que todos los componentes personalizados se procesaron dentro del elemento <p> y estaba usando,

<div>
  <custome-component></custom-component>
</div>

como solución alternativa.

Sin embargo, no es fácil volver a incluir todos los componentes personalizados en el archivo de configuración, como ya hice en el archivo de plantilla de rebajas.

@ li-xinyang Estoy de acuerdo contigo. Agregué una función de detección automática para que no tenga que agregarlos manualmente.
Asegúrese de actualizar el paquete a la última versión 1.1.0 si desea probarlo.
Funciona de inmediato con:

//In your gatsby-config.js ...
plugins: [
  {
    resolve: "gatsby-transformer-remark",
    options: {
      plugins: ["gatsby-remark-component"]
    }
  }
]

Esto es un poco tangente, pero la gente de aquí podría estar interesada en coordinar con @rauchg : ver propuesta

¡@ r24y suena

Creo que hay varias formas de resolver esto que tienen diferentes compensaciones.

No sé si conoce el proyecto llamado Catalog que también admite la inserción de componentes React en Markdown . También hay un complemento de Gatsby llamado gatsby-comment-design-system que intenta adaptar el concepto de Catalog.

Esta solución se ve perfecta @arcticicestudio

El catálogo se ve bien; Y el complemento gatsby-comment-design-system es genial, pero no es compatible con los componentes de React. Sin embargo, creo que hace algo bien, hace uso de la sintaxis del bloque de código existente para agregar una funcionalidad más compleja a Markdown.

Como se discutió varias veces dentro de este hilo, creo que el uso del analizador existente no es la funcionalidad que se desea. Quizás en lugar de elementos React flotantes libres, sería posible denotar más claramente componentes React complejos explícitamente, por ejemplo, un archivo de rebajas puede verse así:

 # Algunos encabezados
 ... etcétera etcétera ...

&lt;Example>
   &lt;Etc />
&lt;/Example>

Cuando queremos que se represente un elemento react incrustado, especificamos el idioma como react , y un analizador compatible con JSX se activa y genera un AST válido que se puede usar con rehype. Si queremos un ejemplo de prisma JavaScript normal, simplemente use el lenguaje normal javascript .

Hola chicos, gran discusión aquí.
Estoy usando gatsby-remark-component y tengo algunas preguntas:

  1. ¿Hay alguna forma de "detectar automáticamente" componentes? Eso eliminaría la necesidad de informar explícitamente a mis componentes en el objeto de componentes:
const renderAst = new RehypeReact({
  createElement: React.createElement,
  components: {

  },
}).Compiler
  1. ¿Hay alguna forma de integrar algunas imágenes con gatsby-remark-images ? Uno de mis objetivos es que el usuario pueda agregar una imagen y enviarla a mi componente a través de accesorios, por ejemplo. Algo como:
    <my-component header-image="[](./image.png)"><my-component>

¡Gracias!

@ThiagoMiranda Sí, (2) ¡sería genial! Mi caso de uso es una galería de imágenes:

<gallery>
  <item source="image1.jpg" caption="One"></item>
  <item source="image2.jpg" caption="Two"></item>
</gallery>

Este analizador de rebajas compatible con JSX de Zeit parece prometedor: https://github.com/mdx-js/mdx

MDX es un superconjunto de la especificación CommonMark que agrega JSX integrado y sintaxis de importación / exportación.

Se basa en el comentario y la repetición, por lo que podría ser un buen reemplazo para su uso en proyectos de gatsby

Escribí un complemento para mdx: https://github.com/nhducit/gatsby-plugin-mdx

genial, quería probar eso con Gatsby :)

¡Usando el complemento mdx de @nhducit , es bastante sencillo conectar páginas MDX!

  1. Agregue la configuración para mdx y la fuente en el directorio pages/ .

gatsby-config.js

module.exports = {
  plugins: [
    'gatsby-plugin-mdx',
    {
      resolve: 'gatsby-source-filesystem',
      options: {
        name: 'pages',
        path: `${__dirname}/src/pages/`,
      },
    },
  ],
}
  1. Consulte todos los archivos de rebajas y cree páginas para cada uno de ellos.

gatsby-node.js

exports.createPages = ({ graphql, boundActionCreators }) => {
  const { createPage } = boundActionCreators

  return new Promise((resolve, reject) => {
    graphql(`
      { 
        allFile(filter:{extension:{eq:"md"}}) {
          edges {
            node {
              absolutePath
              relativeDirectory
              name
            }
          }
        }
      }
    `).then(result => {
      if (result.errors) {
        return reject(result.errors)
      }

      // Create markdown pages.
      result.data.allFile.edges.forEach(({ node: {
        absolutePath,
        relativeDirectory,
        name
       } }) => {
        createPage({
          path: `/${relativeDirectory}/${name}`,
          component: absolutePath
        })
      })
    })
    .then(resolve)
  })
}
  1. Utilice MDX 🎉

src/pages/my-markdown-page.md

import MyComponent from '../components/MyComponent'

# Title

_some content_

<MyComponent />

@avigoldman ¡Agradable! Sería genial ver su ejemplo agregado al archivo README del @nhducit .

¡@avigoldman PR es bienvenido! 👍

@avigoldman parece que este enfoque entra en conflicto con el frontmatter?

@nhducit ¡Haré un PR!

@lintonye, ¿puedes explicar un poco más a qué te refieres? ¿Te refieres a las exportaciones de MDX?

@lintonye, ​​¿ ha intentado utilizar exportaciones mdx? Parece ser un equivalente para mdx: https://github.com/mdx-js/mdx#exports

Corrígeme si me equivoco, pero parece que tenemos que esperar a que Gatsby 2.0 con una versión posterior del paquete web pase los complementos de comentarios a MDX.

cc @KyleAMathews

@avigoldman @nhducit Al exportar datos de los archivos mdx usando la sintaxis de exportación, ¿cómo podemos acceder a eso en nuestra interfaz de usuario cuando se procesan los componentes?

La misma pregunta aquí, con MDX actualmente, no pudo:

  • aplicar estilos personalizados a las páginas de rebajas
  • inyectar contenido de frontmatter como pathContext de exportaciones mdx con nombre
    En realidad, esto podría hacerse, pero esto requiere la creación de un archivo .js para importar el archivo .md, para cada archivo .md, por lo que duplica el trabajo ...

@slorber Tengo una solución bastante hacky en este repositorio: https://github.com/avigoldman/avigoldman.com

Definitivamente no es ideal. Voy a volver a visitar esto una vez que Gatsby V2 esté disponible.

Hola y gracias @avigoldman

También intenté hacer eso aquí https://github.com/nhducit/gatsby-plugin-mdx/issues/13#issuecomment -392334706

Parece que has encontrado la pieza que faltaba. No tuve que extraer correctamente las exportaciones: babel-plugin-config-export

Crea un diseño por página de publicación de blog, no estoy seguro exactamente si se supone que debe hacerse de esta manera o qué tipo de impacto puede tener en el rendimiento de Gatsby, ya que las personas que usan Remark generalmente tienen un solo diseño en su lugar ...

¿Qué pasa con la publicación de su complemento en NPM? esto parece más útil que el que @nhducit hizo con respecto a frontmatter

Además, ¿de dónde viene el fragmento ... mdx graphql?

Acerca de MDX, acaban de agregar un "MDXProvder" (basado en React Context) que puede ser útil para integrar etiquetas personalizadas con Gatsby, cc @avigoldman

@slorber Creé un complemento gatsby-transformer-mdx para poder consultar los archivos MDX.

Estoy tratando cada diseño como una página y cada archivo MDX como el contenido. Entonces, el diseño obtiene el contexto de la página y luego se coloca la MDX (como lo haría con el html generado por comentarios).
Esto no funcionará en Gatsby V2 ya que los componentes de diseño especiales desaparecerán.

¡MDXProvider parece prometedor!

Agregando mis 2 ¢ aquí, me las arreglé para hackear la mayor parte de mi propio sitio web (el repositorio todavía usa Jekyll, pronto se actualizará o agregará un nuevo repositorio) a Gatsby usando mdx gracias a gatsby-transformer-mdx de @ avigoldman.

¡Eso es genial! Debería tener algo de tiempo este fin de semana / la próxima semana para convertirlo en un paquete que funcione bien con Gatsby V2.

@avigoldman una cosa que no pude descifrar de su gatsby-transformer-mdx es el paso de renderizado. gatsby-transformer-comment usa el campo html (que es una cadena), ¿qué usa su transformador? ¿Cómo funciona el cargador de paquetes web si no se requieren en ninguna parte?

Oh, acabo de leer los comentarios anteriores, el truco es que Gatsby v1 envuelve automáticamente todo en un componente de diseño, por lo que estás usando absolutePath para apuntar al archivo MDX. 😃 ¡Gracias por este truco!

@avigoldman ¿ alguna noticia sobre el complemento Gatsby 2? También sería increíble si pudiera dar instrucciones aproximadas sobre cómo lo construiría sin el componente de diseño que ya no existe en Gatsby 2.
¡Gracias!

Tenía la esperanza de poder usar de alguna manera la función export default de MDX, pero pasar cualquier accesorio adicional que no sea children no parece ser un cajero automático. mdx-js / mdx # 187

Si mi RP se fusiona (mdx-js / mdx # 189), creo que podremos usar MDX con gatsby-plugin-mdx y gatsby-transformer-mdx existentes. El único cambio requerido será de nuestra parte, y eso es exportar nuestra plantilla de publicación desde nuestros archivos .mdx :

src/posts/hello-world.mdx :

import Post from '../components/post'

# Hello World

Lorem ipsum.

export default Post

gatsby-node.js :

const path = require('path')

exports.createPages = ({ actions }) => {
  actions.createPage({
    path: '/posts/hello-world',
    component: path.join(__dirname, 'src', 'posts', 'hello-world.mdx'),
    context: { /* passed as pageContext */ }
  })
}

src/components/post.js :

import React from 'react'
import Layout from './layout'

export default ({ children, pageContext }) => (
  <Layout>
    {children}
  </Layout>
)

Creo que esto es realmente crítico. En este momento, todos los complementos gatsby-remark-* están ~ reimplementando un montón de lógica de renderizado que podría y probablemente debería estar en React. Esto podría simplificar mucho las cosas.

@DylanVann eso depende un poco. gatsby-remark-* complementos https://www.gatsbyjs.org/packages/gatsby-remark-images/?=remark-image

Idealmente, por supuesto, mezclamos ambos mundos.

@KyleAMathews Sí, significaría algo más de JS en el lado del cliente, aunque todavía se entregaría primero como HTML estático. Creo que, de todos modos, es probable que mucha gente envíe gatsby-image para algunas partes de su sitio, por lo que en ese caso la duplicación es un problema menor.

Entiendo que hay utilidad en los complementos gatsby-remark-* . Sin embargo, la lógica de renderizado específicamente, que actualmente se realiza con cadenas, parece que podría hacerse en React.

Tengo este tipo de trabajo con el método htmlAst / rehype-react .

Parece así, pero en la práctica es mucho más complicado. Si cree que está en algo, podría plantear un nuevo problema con una propuesta enfocada.

Parece un problema difícil de resolver. Lamentablemente, no creo que tenga tiempo de implementar nada o hacer una propuesta. La idea de hacer complementos remark parcialmente usando componentes personalizados de React definitivamente funciona, tengo un código que lo usa.

Esto es generado por @dylanvann/gatsby-remark-cloudinary partir de imágenes de rebajas que terminan en mp4 . La idea es optimizar los videos (dimensionar en el momento de la construcción, agregar carteles). Sin embargo, quería la lógica de renderizado en React. El procesamiento del video se realiza en otra función, pero esto es parte de lo que se reemplaza el HTML del nodo.

export const videoHTML = ({
    srcVideo,
    srcVideoPoster,
    base64,
    paddingBottom,
    presentationWidth,
}) =>
    `<cloud-video srcvideo="${srcVideo}" srcvideoposter="${srcVideoPoster}" base64="${base64}" paddingbottom="${paddingBottom}" presentationwidth="${presentationWidth}"></cloud-video>`

Luego, use un componente personalizado con rehype-react .

import React from 'react'
import rehypeReact from 'rehype-react'
import CloudVideo from './CloudVideo'

const renderAst = new rehypeReact({
  createElement: React.createElement,
  components: {
    'cloud-video': CloudVideo,
  },
}).Compiler

const Markdown = ({ ast }) => renderAst(ast)

Markdown.propTypes = {
  ast: PropTypes.object,
}

export default Markdown

El ast se puede extraer de GraphQL.

Entonces, este componente funciona para SSR y el lado del cliente. De todos modos, sé cómo es con OSS. Solo digo que creo que sería una gran característica y podría reducir la complejidad del código, por lo que sería genial si alguien tuviera tiempo para encontrar mejores soluciones.

No estoy en desacuerdo con nada de lo que está diciendo, creo que comenzar una buena discusión sería mucho mejor en su propio tema, en lugar de al final de un hilo muy cargado de más de 60 comentarios. 😉

@Avigoldman y yo gatsby-mdx para albergar integraciones y utilidades MDX ambiciosas compatibles con 2.0.

Actualmente, las páginas de gatsby .mdx funcionan de forma predeterminada después de habilitar el complemento y se han agregado las siguientes características adicionales en la parte superior de mdx:

  • Usar y consultar frontmatter clásico y estilo JSON
  • Definir diseños predeterminados para archivos mdx que no definen uno

También estamos planeando integraciones más sofisticadas para

  • procesamiento de imágenes avanzado
  • complementos personalizados md y hast.
  • compatibilidad con los mismos campos que gatsby-transformer-comment

Todavía estamos en una etapa muy temprana del ciclo de vida, así que avísenos si tiene algún problema y lo haremos :)

@ChristopherBiscardi ¿ está destinado a ser utilizado en combinación con gatsby-plugin-mdx o en su lugar?

@silvenon Parece que gatsby-plugin-mdx quedará obsoleto y, por lo tanto, se detendrá en 1.0, mientras que gatsby-mdx avanzará con 2.0 y más allá.

@ m-allanson cree que es seguro cerrar este tema ahora que tenemos gatsby-mdx ?

Creo que sí, gracias a todos 🎉

Entonces, ¿ gatsby-mdx ahora se preferirá a rehype-react junto con gatsby-transformer-remark como se describe aquí ?

Si la respuesta no es un sí claro, ¿alguien podría explicar las ventajas y desventajas de ambos enfoques?

Creo que esta parte de esa publicación de blog responde a tu pregunta. rehype-react proporciona elementos HTML personalizados que se asignan a los componentes de React, pero MDX en realidad es JSX dentro de Markdown, es más predecible y tiene menos advertencias.

No estoy en el equipo de Gatsby, pero diría que sí, gatsby-mdx es la forma preferida de React en Markdown.

@janosh , hasta donde yo sé, gatsby-mdx no puede reemplazar completamente a gatsby-transformer-comment
parece que todavía se pierden gatsby-comment-images & gatsby-comment-copy-linked-files, por ejemplo y otros complementos de gatsby-comment
Creo que están trabajando en ello, pero no están seguros del estado actual.

Pero si no necesita esos complementos o puede esperar, diría que sí, al menos lo preferiré, me parece más limpio.

@CanRau Estoy refundando eso hoy (https://github.com/ChristopherBiscardi/gatsby-mdx/pull/68) con la intención de fusionar y lanzar. Probablemente habrá algunos casos extremos que tenemos que tratar, pero voy a ir a través de algunos de ellos hoy en funcionamiento antes de que se fusionan.

El estado del PR es que los complementos gatsby-comment- * se aplican correctamente, pero hay diferencias en cómo la salida de, digamos, el complemento gatsby-comment-prismjs (que actualmente produce una salida HTML) se maneja mediante transformer-comment vs mdx's tubería. Considero que el soporte para complementos como gatsby-comment-prismjs es importante, pero también un enfoque subóptimo. Un mejor enfoque en el mundo MDX es usar algo como prism-react-renderer como el elemento code en un MDXProvider , lo que le daría total flexibilidad y control sobre el renderizado en comparación con complementos de comentarios para lograr un efecto similar (y también le permite compartir ese componente con contenido que no es mdx como páginas .js).

Estoy mucho más preocupado con el funcionamiento de los archivos vinculados con copia y el procesamiento de imágenes que con el trabajo de prismjs para la primera versión del soporte del complemento gatsby-comment- *.

Suena increíble @ChristopherBiscardi, especialmente archivos con enlaces de copia y soporte de imágenes, me encantaría ayudar, pero hablando de manera realista, no creo que pueda manejarlo en este momento, ya que estamos realmente llenos ^^
Tal vez pueda compartir algunos comentarios, creo que lo intentaré con algunas metapáginas más pequeñas para probar cosas

Es interesante saber que estás transmitiendo tu trabajo ... Soy bastante nuevo en las cosas en vivo y todavía no entiendo cómo saber cuándo vas a vivir ... Probablemente solo funciona con una cuenta, supongo

Feliz de tener su ayuda en cualquier momento en el futuro si tiene tiempo, no dude en enviarme un ping si tiene preguntas :) Los comentarios en sí ayudan mucho de cualquier manera, así que si lo prueba, asegúrese de presentar problemas.

Es interesante saber que estás transmitiendo tu trabajo ... Soy bastante nuevo en las cosas en vivo y todavía no entiendo cómo saber cuándo vas a vivir ... Probablemente solo funciona con una cuenta, supongo

Configuré un "calendario" de horarios de transmisión en la parte inferior de mi canal de Twitch . Sé que si alguien tiene una cuenta de Twitch y me sigue, recibirán notificaciones cuando esté en vivo, pero de lo contrario, el horario es donde buscar. Estoy bastante seguro de que puedes ver si tienes una cuenta o no. Soy un poco nuevo en la transmisión (solo lo he estado haciendo un par de semanas), así que siempre estoy abierto a mejores formas de hacer este tipo de cosas. Algunas personas han venido repetidamente y pasan el rato / miran / hablan en el chat, lo cual es bastante divertido :)

screen shot 2018-08-28 at 1 17 05 pm

Está bien, es bueno saberlo

y seguramente publicaré problemas cuando encuentre alguno;)

Por cierto, desde que se mencionó Prism, solo me gustaría agregar que idealmente los complementos de comentario / reenvío deben usarse directamente, MDX lo admite a través de las opciones mdPlugins y hastPlugins (esto se puede pasar a través de gatsby -mdx). Se pueden agregar complementos como @ mapbox / rehype-prism a hastPlugins , pero hubo algunos problemas de espacios en blanco que solucioné en mdx-js / mdx # 226, por lo que una vez que se fusiona y se libera, el resaltado de sintaxis será bueno ¡ir!

si ... totalmente. gatsby-mdx ya admite la transferencia de complementos de comentario / actualización al núcleo de mdx. Aquí está @ mapbox / rehype-prism, por ejemplo (tomé ese ejemplo de algunas de sus discusiones de relaciones públicas / problemas originalmente @silvenon , gracias). AFAIK rehype prism no admite complementos de prisma, por lo que siempre es una compensación dependiendo de los casos de uso (creo que usar complementos de rehype para prisma significa que tendrá más dificultades para integrar algo como react-live , por ejemplo)

gatsby-comment-prismjs y otros complementos de gatsby-comment- * se lanzaron en 0.1.1 hoy, por lo que ahora hay al menos 3 opciones para resaltar la sintaxis entre rehype / comment / react-components 😝

¿Fue útil esta página
0 / 5 - 0 calificaciones