Diseño de una aplicación de toma de notas Markdown en ReactJS

En este artículo, aprenderemos cómo diseñar una aplicación de toma de notas Markdown en React que puede ayudar a tomar notas rápidamente y descargar el resultado renderizado. El uso de Markdown permite dedicar menos tiempo a formatear el texto y, por lo tanto, crear contenido de texto enriquecido utilizando solo la sintaxis de Markdown .

Usaremos la biblioteca React para crear rápidamente la interfaz de usuario, ya que manejaría la actualización del DOM según sea necesario. Usaremos Bootstrap CSS para diseñar la aplicación y hacerla fácil de usar. También usaremos un Blob para guardar el contenido en nuestro dispositivo.

Seguiremos los siguientes pasos para crear nuestra aplicación:

Paso 1: Crear el proyecto

Comenzaremos creando un nuevo proyecto de reacción usando la herramienta create-react-app . Puede usar el siguiente comando para crear uno con el nombre deseado. Asegúrese de que Node y npm estén instalados en el sistema.

npx create-react-app react-md-note-app

Estructura del proyecto: A continuación, eliminaremos todos los archivos que no sean necesarios. La estructura de archivos después de eliminar los archivos se muestra a continuación:

Directorio de proyectos

Paso 2: Instalación de los módulos necesarios

Comenzaremos agregando Bootstrap CDN a la página index.html. Los enlaces CDN se pueden encontrar aquí y se pueden agregar directamente en la sección principal de la página de índice.

También necesitaremos dos paquetes npm , uno es el paquete markdown-it que hace el trabajo pesado de analizar el contenido de Markdown y brindarnos la salida representada en HTML. Simplemente podemos usar este HTML para mostrar nuestra salida. El otro módulo es el paquete de ahorro de archivos que simplifica la tarea de guardar el blob dado en el sistema. El siguiente comando se utiliza para instalar estos dos paquetes:

npm install markdown-it file-saver

Paso 3: Creación de una interfaz de usuario simple usando Bootstrap

Crearemos el diseño utilizando el sistema Bootstrap Grid para garantizar que nuestra aplicación responda a dispositivos móviles y se vea bien sin escribir mucho CSS.

La aplicación se puede dividir en 3 partes; el editor de Markdown que permitirá al usuario ingresar las notas en Markdown, el área de salida que muestra el HTML renderizado y las opciones para guardar archivos que contienen el campo de entrada para el nombre del archivo y los botones para guardar el contenido. Cada una de las partes se anida utilizando el componente Tarjeta de Bootstrap y los componentes relevantes se agregan a los elementos de entrada.

También necesitaremos algunas reglas CSS que se pueden importar a nuestro archivo App.js. Podemos crear un nuevo archivo llamado App.css y escribir las reglas de la siguiente manera:

Aplicación.css:

CSS

body {
  background-color: yellow; 
} 
.markdown-editor, .rendered-output {
  height: 100%;
  width: 100%;
  padding: 10px; 
} 
.markdown-textarea, .rendered-html-output {
  height: 60vh;
  width: 100%;
  overflow: auto;
}

Paso 4: Crear los ganchos que se usarán para administrar el estado

Crearemos 3 ganchos usando el método useState de React para administrar el estado en las 3 partes de nuestra aplicación. Cada uno de los ganchos devuelve la propia variable con su estado inicial y la función que se puede utilizar para establecer el estado de esa variable. React volverá a renderizar automáticamente el componente cuando cambie su estado.

Esto nos permitirá simplemente usar las funciones respectivas y las variables para manejar el estado de cada componente.

Paso 5: Uso de las variables de estado en la aplicación

Ahora usaremos estas variables dentro de los 3 componentes que creamos anteriormente.

La variable markdownText se usa en el área de texto donde escribiremos nuestro texto de descuento. Usaremos esto en la propiedad de valor del área de texto . Usando la función setMarkdownText podemos cambiar el valor del texto aquí y se mostraría a través de esta propiedad de valor .

La variable renderingHTML se usa en el elemento div que mostrará la salida renderizada de la rebaja . Como el módulo MarkdownIt devolverá el HTML del descuento, necesitaremos configurar el HTML interno de este elemento directamente. Esto requerirá el uso de la propiedad peligrosamente SetInnerHTML del elemento y pasar un objeto con la clave de _html.

Nota: Esta es una función en React que desalienta la práctica de modificar directamente el HTML para evitar ataques de Cross-Site Scripting (XSS) en una página web. Se recomienda desinfectar cualquier contenido HTML ingresado por el usuario antes de usarlo directamente.

Finalmente, la variable fileName se usa en las opciones del protector de archivos para que pueda usarse para ingresar el nombre de archivo del contenido que se guardará. También vincularemos el controlador de eventos onChange a setFileName para que cualquier valor ingresado por el usuario se actualice a la variable. Podemos hacer esto accediendo al objetivo del evento y obteniendo la propiedad de valor.

Paso 6: Creando las funciones que hemos definido anteriormente

La función handleTextInput(): esta función tomará el texto que se ingresa en el editor de rebajas y usará MarkdownIt para representar el HTML necesario.

Primero obtendremos el texto que se ingresa al obtener el valor del objetivo. Luego inicializamos una nueva instancia de MarkdownIt y usamos su método de renderizado. Luego usaremos la función setMarkdownHTML para establecer esto en el área de salida donde se mostrará nuestro HTML final. Esta función se usará en la propiedad onChange del editor de rebajas.

Las funciones saveHTML() y saveMarkdown(): estas funciones se utilizarán para guardar contenido en nuestro sistema con el nombre de archivo dado. En ambas funciones, crearemos un objeto Blob con el contenido a guardar. Podemos usar las variables renderingHTML y markdownText para obtener el contenido de texto actual de la aplicación.

El tipo del blob se especifica a continuación. Podemos usar texto/html para la salida renderizada para que se guarde como un archivo HTML y solo texto para el texto de descuento.

Ahora usaremos el método saveAs() del módulo FileSaver para guardar el archivo en el sistema. Este método usa dos parámetros, el primero es el objeto blob que debe guardarse y el segundo es el nombre del archivo que debe usarse para guardar el archivo. Podemos obtener el nombre del archivo usando la variable fileName y pasar el objeto blob que creamos anteriormente. 

Podemos vincular estas funciones con los respectivos controladores de eventos onClick de los dos botones que hemos creado. Al hacer clic en los botones, se abrirá un cuadro de diálogo Guardar como en el navegador con el nombre de archivo dado y el usuario puede optar por guardar el archivo según sea necesario.

Aplicación.js:

Javascript

import { useState } from 'react';
  
// Import the required modules
import MarkdownIt from 'markdown-it';
import FileSaver from 'file-saver';
  
import './App.css';
  
function App() {
  
  // Create the states that will be used 
  // through the application
  // This state will be used for the Markdown text
  let [markdownText, setMarkDownText] = useState("");
  
  // This state will be used for the rendered HTML
  let [renderedHTML, setRenderedHTML] = useState("");
  
  // This state will be used for the filename while saving
  let [fileName, setFileName] = useState("untitled-note");
  
  // Create a function that will be invoked
  // whenever the user modifies the content
  // in the textarea
  function handleTextInput(e) {
  
    // Change the text of the markdown side
    setMarkDownText(e.target.value);
  
    // Initialize a MarkdownIt instance
    let md = new MarkdownIt();
  
    // Render out the markdown to HTML using
    // the render() method
    let renderedHTML = md.render(e.target.value);
  
    // Change the markdown's side to the rendered HTML
    setRenderedHTML(renderedHTML);
  }
  
  // Create a function download the rendered HTML
  function saveHTML() {
  
    // Create a new Blob of the type 'text/html'
    // using the rendered HTML content
    let blobFile = new Blob([renderedHTML], {
      type: "text/html"
    });
  
    // Save the file using the given file name
    FileSaver.saveAs(blobFile, fileName);
  }
  
  // Create a function download the Markdown text
  function saveMarkdown() {
  
    // Create a new Blob of the type 'text'
    // using the markdown content
    let blobFile = new Blob([markdownText], {
      type: "text"
    });
  
    // Save the file using the given file name
    FileSaver.saveAs(blobFile, fileName);
  }
  
  return (
    <div className="container">
      <h2 className="app-heading text-center
                     display-4 my-3">
        React Markdown Notes
      </h2>
      <div className="row">
        <div className="col col-sm-12 col-md-6">
  
          {/* Card for the markdown editor */}
          <div className="card bg-light markdown-editor">
            <h4 className="card-title text-center">
              Markdown
            </h4>
            <div className="card-body">
  
              {/* Textarea for the markdown editor */}
              <textarea
                className="form-control markdown-textarea"
                rows={20}
                value={markdownText}
                onChange={handleTextInput}
              ></textarea>
            </div>
          </div>
        </div>
        <div className="col col-sm-12 col-md-6">
  
          {/* Card for the markdown editor */}
          <div className="card bg-light rendered-output">
            <h4 className="card-title text-center">
              Output
            </h4>
  
            {/* Textarea for the markdown editor */}
            <div className="card-body">
              <div
  
                // Change the HTML to be displayed according
                // to the render produced by MarkdownIt
                dangerouslySetInnerHTML={{ __html: renderedHTML }}
                className="rendered-html-output"
              >
              </div>
            </div>
          </div>
        </div>
      </div>
  
      <div className="row">
        <div className="col col-sm-12">
  
          {/* Card for the save files option */}
          <div className="card bg-light my-3">
            <div className="card-body">
              <h4>Save Content</h4>
              <div className="input-group">
                <input
                  type="text"
                  className="form-control"
                  placeholder="File name"
                  aria-label="File name"
                  value={fileName}
                  onChange={fname => setFileName(fname.target.value)}
                />
  
                {/* Buttons for saving the text */}
                <div className="input-group-append">
                  <button className="btn btn-primary" 
                          type="button" 
                          onClick={saveMarkdown}>
                            Save Markdown
                  </button>
                  <button className="btn btn-primary" 
                          type="button" 
                          onClick={saveHTML}>
                            Save HTML
                  </button>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  )
}
  
export default App;

Paso 6: Ejecutar y compilar la aplicación

Podemos ejecutar esta aplicación usando el siguiente comando. Esto iniciará el servidor de desarrollo de React que se puede usar para depurar nuestra aplicación.

npm run start

También podemos crear esta aplicación para que se pueda alojar en cualquier plataforma que admita el alojamiento de archivos estáticos. Podemos construir nuestra aplicación usando el siguiente comando para ejecutar el proyecto:

npm run build

Producción:

Código fuente: https://github.com/sayantanm19/react-markdown-notes-gfg

Publicación traducida automáticamente

Artículo escrito por sayantanm19 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *