Skip to content

Support for Exotics  #22

Closed
Closed
@shellscape

Description

@shellscape

Initial checklist

Problem

This is arguably outside of the scope of the reason that hastscript exists, and I fully acknowledge that. However, I do believe it would be a value add.

I'm working on jsx-email and one of my goals to have cross-framework compatibility with the components it exports - effectively untethering from requiring react as a dependency. One of the bananas scenarios there is that users are running the components it exports in several different environments, one of which is Storybook. Since it has a few components that perform async operations, it needs to use <Suspense/>. Similar to Fragment in react, this is a symbol with children, with the added fallback prop.

I put together a little test script to see what would happen should I inject react-specific JSX into the generic JSX supported by hastscript:

/** @jsxImportSource hastscript */

import { h } from 'hastscript';
import { toJsxRuntime } from 'hast-util-to-jsx-runtime';
import { Suspense } from 'react';
import * as reactRuntime from 'react/jsx-runtime';

const component = (
  <>
    <Suspense fallback={<div>waiting</div>}>
      <div class="foo" id="some-id"></div>
    </Suspense>
  </>
);

console.log(component);
console.log();
console.log(toJsxRuntime(component, reactRuntime as any));

I was pleasantly surprised to find that it handled the Suspense "component" there quite gracefully by simply discarding it:

{
  type: 'root',
  children: [
    {
      type: 'element',
      tagName: 'div',
      properties: [Object],
      children: [Array]
    }
  ]
}

But that result (in this potentially erroneous context) discards the Suspense component altogether. Using hast-util-to-jsx-runtime to convert it to React predictably results in the missing Suspense component.

To that end, I'd love to see support for exotic components (which may just be symbols that have props) in hastscript. While probably not the intended use it would open up some new possibilities for this lib's use.

Solution

I'm not quite sure how this would be accomplished, and since I'm in an evaluation phase of possible broader solutions for my use-case, I haven't done a deep dive on the code here to suggest a path forward. I would love to get your initial thoughts on how this might be supported.

Alternatives

I've been unsuccessfully working on a generic renderer that can handle JSX formats of React, Preact, and SolidJS. The variances are significant and I haven't been able to accommodate them all - and that doesn't even go into the type incompatibilities between them. Coupled with the fact that I'd have to race to keep up with any changes in each framework, it seems like a losing path over time. I was excited to find this and hast-util-to-jsx-runtime because it opens a new path where I can write my components in a standard which can then be converted to the appropriate format for each.

Metadata

Metadata

Assignees

No one assigned

    Labels

    👎 phase/noPost cannot or will not be acted on🙋 no/questionThis does not need any changes

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions