Code Monkey home page Code Monkey logo

Comments (9)

bastienrobert avatar bastienrobert commented on September 28, 2024 8

@thomasbritton I've created a React component to render RichTexts, I think it might be optimized but it works for the moment

import React, { ReactNode } from 'react'
import classnames from 'classnames'

import css from './RichText.module.scss'

interface RichTextASTNode {
  type: string
  children: RichTextASTNode[]
  level?: number
  value?: string
  bold?: boolean
  italic?: boolean
  url?: string
  title?: string
  target?: string
  listType?: string
}

interface RichTextProps {
  className?: string
  data: RichTextASTNode
}

export function RichText({ className, data }: RichTextProps) {
  return (
    <div className={classnames(css.RichText, className)}>
      {serializeRichTextASTNode(data)}
    </div>
  )
}

/**
 * @workaround `@shopify/hydrogen-react` package does not export a RichText serializer function.
 * @see https://github.com/Shopify/hydrogen-react/issues/150
 * @todo Remove this workaround once the issue is resolved.
 *
 * @todo Should support internal links (there's no Shopify option in RichText for this right now)
 */
function serializeRichTextASTNode(
  node: RichTextASTNode,
  index: number = 0,
): ReactNode {
  switch (node.type) {
    case 'root':
      return (
        <div key={index}>{node.children.map(serializeRichTextASTNode)}</div>
      )
    case 'heading':
      return React.createElement(
        `h${node.level}`,
        null,
        node.children.map(serializeRichTextASTNode),
      )
    case 'paragraph':
      return <p key={index}>{node.children.map(serializeRichTextASTNode)}</p>
    case 'text':
      return (
        <span
          key={index}
          style={{
            fontWeight: node.bold ? 'bold' : undefined,
            fontStyle: node.italic ? 'italic' : undefined,
          }}>
          {node.value}
        </span>
      )
    case 'link':
      return (
        <a key={index} href={node.url} title={node.title} target={node.target}>
          {node.children.map(serializeRichTextASTNode)}
        </a>
      )
    case 'list':
      const List = node.listType === 'unordered' ? 'ul' : 'ol'
      return (
        <List key={index}>
          {node.children.map((item) => (
            <li key={item.children[0].value}>
              {item.children.map(serializeRichTextASTNode)}
            </li>
          ))}
        </List>
      )
    default:
      return null
  }
}

export function toString(node: RichTextASTNode, result: string[] = []): string {
  switch (node.type) {
    case 'root':
      node.children.forEach((child) => toString(child, result))
      break
    case 'heading':
    case 'paragraph':
      node.children.forEach((child) => toString(child, result))
      result.push(' ')
      break
    case 'text':
      result.push(node.value || '')
      break
    case 'link':
      node.children.forEach((child) => toString(child, result))
      break
    case 'list':
      node.children.forEach((item) => {
        item.children.forEach((child) => toString(child, result))
        result.push(' ')
      })
      break
  }

  return result.join('').trim()
}

from hydrogen.

davidhousedev avatar davidhousedev commented on September 28, 2024 2

Exciting to see rich text support getting worked on! Just wanted to call out that we've had really great experiences with the Contentful rich text schema. Specifically, one of the most useful features is the ability to inject either inline or block entity references. That has enabled us to e.g. personalize marketing copy using a customer's name or render an interactive React component within the copy.

I have a lot of first-hand experience working with Contentful rich text, happy to provide more context if that helps!

from hydrogen.

thomasbritton avatar thomasbritton commented on September 28, 2024 1

Any update on this?

Is there any other work-arounds that are possible to get working with a rich-text metafield within Hydrogen?

from hydrogen.

joe-szczepaniak avatar joe-szczepaniak commented on September 28, 2024

Having discussions around AST and the GraphQL API.

  • Sanity call as an action item with Kusum.
  • Slack coordination as an action item.

from hydrogen.

elisenyang avatar elisenyang commented on September 28, 2024

hey @TirmanSidhu @joe-szczepaniak - Can you please provide more context on this? Are there any specific requirements you need from the Hydrogen Metafield component?

from hydrogen.

TirmanSidhu avatar TirmanSidhu commented on September 28, 2024

Hi @elisenyang, we are just sorting out the AST structure we plan to use for storing the metafield value, but also considering return serialized HTML to consumers for the initial release, since this might get us more adoption from developers. I'll reach out as soon as we are settled on something!

from hydrogen.

camielvs avatar camielvs commented on September 28, 2024

With Tirman moving on the status of this is unknown. If anyone has any updates, please advise!

from hydrogen.

benjaminsehl avatar benjaminsehl commented on September 28, 2024

@bastienrobert, impressive work! If you're interested, would love if you started a PR that we could collaborate on?

There are few things that would be great to add in the future, but this would be a great start on a v1. Only real comments are allowing an as prop for the parent node (still default to div), and then not assuming a CSS strategy, and not depend on classnames.

from hydrogen.

benjaminsehl avatar benjaminsehl commented on September 28, 2024

One thing we'd love to provide is an ergonomic like …

<RichText 
  data={data}
  components={
    h1: (content) => <h1>...</h1>
    h2: (content) => ...
    ....
  }
/>

To provide more control over the rendering.

from hydrogen.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.