thompsonsj/slate-serializers

Difficult to map multiple html elements to a single slate element

Opened this issue · 0 comments

Love this library, but hit a snag:

I have html like this

<figure><img src="https://example.com/image.jpg" alt="An image" /><figcaption>An image</figcaption></figure>

Ideally, I want to map this in slate with htmlToSlate to:

  {
          type: "image",
          url: "https://example.com/image.jpg",
          alt: "An image",
          caption: "An image",
          children: [{ text: "" }],
        },

Currently, this is quite difficult to do because you either:

  • query the parent of img to look for figures but then you end up wrapped inside your default element e.g. a paragraph and figcaption has its own text node
  • query img in figure and set the attributes, but then you end up with extra children you don't want

Only workaround i've found is super hacky:

 htmlUpdaterMap: {
    figure: el => {
      // strip all the child nodes from figures with images to make them flat for the elementMap
      const caption = findOne(node => node.name === "figcaption", [el]);
      const img = findOne(node => node.name === "img", [el]);
      if (!img) {
        return el;
      }
      const src = img.attribs.src;
      const alt = img.attribs.alt;
      return new Element(
        "figure",
        {
          ...el.attribs,
          "data-caption": caption ? textContent(caption) : "",
          "data-src": src,
          "data-alt": alt,
          "data-type": "image",
        },
        []
      );
    },
  },

Then I can add in a elementMap and extract these data attributes.

It would be nice if there was some nice way of mapping multiple dom nodes down to a single slate element