Giter Site home page Giter Site logo

Comments (9)

ChristianMurphy avatar ChristianMurphy commented on July 17, 2024

@jaens could you give an example of when this happens?
The docs in rehype-react show processand processSync https://github.com/rhysd/rehype-react#use
Using the process methods may work better with TS typings.


I'm cautious about using stringify to return a non-string or setting it's typescript type to non-string, as this seems to run counter to its intended use.

from unified.

wooorm avatar wooorm commented on July 17, 2024

.stringify is indeed “supposed” to return a string. Or at least the “compiled” syntax tree. All the compilers that go to a virtual DOM (remark-vdom, remark-react, rehype-react, etc) benefit from the fact that it doesn’t have to be.

In fact, anything returned by compiler (or Compiler#compile) is returned by .stringify.
When using .process, that value is set on file.contents, which typically would be string or Buffer, but can also be anything.


I'm cautious about using stringify to return a non-string or setting it's typescript type to non-string, as this seems to run counter to its intended use.
ChristianMurphy

Yeah, I feel the same way.

from unified.

jaens avatar jaens commented on July 17, 2024

This is for a two-stage pipeline, so process is not an option, I think.

The first stage runs the parser, extracts the metadata etc., and the second stage renders the result from the first stage into React (this is done in two stages because this is a multi-page renderer with interdependencies between pages).

The code is roughly:

// Stage 1 (vfile as input, node as output)
let processor = unified()
      .use(remark_parse)
      .use(remark_frontmatter, "yaml")
      .use(frontMatterExtractor);

let node = await processor.run(await processor.parse(vfile), vfile);
// Stage 2 (node as input, vfile as input, React as output)
let processor = unified().use(rehype_react, {
      createElement: React.h
});
return ((await processor.stringify(
      node,
      vfile
    )) as any) as React.VNode;

from unified.

ChristianMurphy avatar ChristianMurphy commented on July 17, 2024

@jaens from the sample code above, process should work fine

import * as React from "react";
import { render } from "react-dom";
import unified from "unified";
import remarkParse from "remark-parse";
import remarkFrontmatter from "remark-frontmatter";
import remarkReact from "remark-react";

const { contents } = unified()
  .use(remarkParse)
  .use(remarkFrontmatter)
  .use(remarkReact)
  .processSync("# hello from remark");

function App() {
  return <>{contents}</>;
}

const rootElement = document.getElementById("root");
render(<App />, rootElement);

live demo: https://codesandbox.io/s/unified-react-typescript-process-wepo4

this is done in two stages because this is a multi-page renderer with interdependencies between pages

This sounds like something that could be done in a plugin, but it's hard to tell without an example of "interdependencies" is.
Is there a more complete example you could share in a CodeSandbox?

from unified.

jaens avatar jaens commented on July 17, 2024

The example you pasted above does not allow to inspecting all the vfiles/nodes between the parsing and rendering (as I said, process is not an option I think).

First, to clarify, this is about rendering multiple documents at once (in a static site generator).

Let's say you have an "all pages" React component you can have in the Markdown (that renders the list of all the pages in the site).
To render that, you need the titles of all the pages.

So you do two stages:

  1. Parse all the Markdown pages and extract front matters (title).
  2. Render all the Markdown pages (so they can use the "all pages" component).

from unified.

ChristianMurphy avatar ChristianMurphy commented on July 17, 2024

Let's say you have an "all pages" React component you can have in the Markdown (that renders the list of all the pages in the site).
To render that, you need the titles of all the pages.

Another approach would be to copy the metadata into vfile.data and rendering the "all pages" component outside of remark-react.
E.G. https://codesandbox.io/s/unified-react-typescript-process-7hd51


Going back to

Not sure what's the best solution here.

  • Specify the "stringed" type as a generic parameter somewhere?

This might be a possibility.
My caution here is that we could get into a different typing mismatch mess doing this, if the generics cannot be inferred from the Parser and Compiler classes.

For example

(processor.stringify(node, vfile) as unknown) as VNode;

is not all that different from

processor.stringify<VNode>(node, vfile);

In that the type that is being cast/genericized may conflict with the type the Compiler is returning, and TypeScript would be none the wiser.

We'd need to look into feasible to make Parser and Compiler generic and have that bubble up from the plugins into unified.

/cc @Rokt33r

  • Make the return type any?

any should be avoided in the typings, any disables the type system for a variable/indentifier, which largely defeats the purpose of having types and typings.

from unified.

jaens avatar jaens commented on July 17, 2024

Yes, changing the architecture so it doesn't allow arbitrary/generic components in Markdown of course "solves" this problem, but for a generic static site generator it's not really workable (it's desirable to allow anything anywhere instead of forcing one-off hacks for eg. sitemap or category pages).

re: the "actual" typing, looks like this is probably a bit tricky, as the type of the Processor can change depending on what .use() you call on it - so looks like it would require adding generic type parameters to the Plugin, Compiler and Processor types and somehow propagating all of that through .use()...

from unified.

Rokt33r avatar Rokt33r commented on July 17, 2024
stringify<P = string>(node: Unist.Node, file?: VFileCompatible): P

Would be the best option I guess?

re: the "actual" typing, looks like this is probably a bit tricky, as the type of the Processor can change depending on what .use() you call on it - so looks like it would require adding generic type parameters to the Plugin, Compiler and Processor types and somehow propagating all of that through .use()...

It would be nice to have. But I'm afraid that the propagating should be quite difficult to implement and buggy.

from unified.

wooorm avatar wooorm commented on July 17, 2024
stringify<P = string>(node: Unist.Node, file?: VFileCompatible): P

@Rokt33r So that fixes this issue?

You’re suggesting to replace:

stringify(node: Node, file?: VFileCompatible): string

with the above right?

It would be nice to have. But I'm afraid that the propagating should be quite difficult to implement and buggy.

Yeah

from unified.

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.