facebook / docusaurus

Easy to maintain open source documentation websites.
https://docusaurus.io
MIT License
55.66k stars 8.34k forks source link

Make most features work in CommonMark mode: head, live code blocks, tabs... #9092

Open slorber opened 1 year ago

slorber commented 1 year ago

Motivation

Related to the CommonMark support issue: https://github.com/facebook/docusaurus/issues/3018

Some custom elements we created do not work when using the CommonMark parser mode, that you can turn on using:


I think it would be convenient for users to have features working fine in both modes in a consistent way. I believe it is possible, but may require some adaptations.

Here are some components that do not currently work:


SEO

This should work in CommonMark too, but currently does not:

<head>
  <title>HEAD Markdown Page tests title</title>
  <meta name="keywords" content="cooking, blog">
</head>

Summary/details

Renders as:

CleanShot 2023-06-22 at 17 06 05

Instead of:

CleanShot 2023-06-22 at 17 07 11


Live code editor

Renders as:

CleanShot 2023-06-22 at 17 07 58

Instead of:

CleanShot 2023-06-22 at 17 07 28


Tabs

Renders as: N/A because we don't have any syntax that does not require using MDX/ESM imports.

Instead of:

CleanShot 2023-06-22 at 17 08 35

Possible solution? IMHO this syntax should be allowed without imports:

<tabs>
  <tabItem value="apple" label="Apple" default>
    This is an apple 🍎
  </tabItem>
  <tabItem value="orange" label="Orange">
    This is an orange 🍊
  </tabItem>
  <tabItem value="banana" label="Banana">
    This is a banana 🍌
  </tabItem>
</tabs>

Structured data

As part of https://github.com/facebook/docusaurus/pull/9669 we are adding a @theme/StructuredData helper component:

import StructuredData from "@theme/StructuredData";

<head>
  <meta name="keywords" content="cooking, blog" />
  <meta name="twitter:card" content="summary_large_image" />
  <link rel="preconnect" href="https://example.com" />
  <StructuredData structuredData={{
    '@context': 'https://schema.org/',
    '@type': 'Organization',
    name: 'Meta Open Source',
    url: 'https://opensource.fb.com/',
    logo: 'https://opensource.fb.com/img/logos/Meta-Open-Source.svg',
  }} />
</head>

# Title

We should figure out how to define structured data in CommonMark mode

Self-service

Josh-Cena commented 1 year ago

Is my understanding correct that CommonMark mode does not allow providing custom components at all? If so, do we need to walk the React element tree created by mdx-loader in client code so we can inject our React components?

It seems rather imperative for us to make <details> and live code blocks work, but I'm not sure about tabs, considering we've always advocated them as an MDX-special feature, and people migrating from legacy (non-Docusaurus2) systems aren't likely going to use them anyway.

slorber commented 1 year ago

Is my understanding correct that CommonMark mode does not allow providing custom components at all?

It does not allow the usage of JSX when parsing the input, but it still compiles to React components, and you can process the AST so that it outputs what you want, reading components from the provider.

I recently added a few useful options to the MDX playground to make this easier to understand.

CleanShot 2023-06-22 at 17 19 35

Note: when using the lowercase <summary>, the MDX rehype serializer output will not "read from the MDXProvider". To do so, we'd just have to capitalize it, and the output would then read from the MDXProvider and use the appropriate theme component.


What I mean is technically nothing prevents of from offering a feature parity for most of these features, so if we can, why not!

slorber commented 1 year ago

Hmmm my mistake, with CommonMark mode even lowercase elements seem to be able to read from the provider:

function _createMdxContent(props) {
  const _components = Object.assign({
    details: "details",
    summary: "summary",
    p: "p"
  }, props.components);
  return _jsxs(_components.details, {
    children: ["\n  ", _jsx(_components.summary, {
      children: "MD Summary"
    }), "\n", _jsx(_components.p, {
      children: "Our custom Details/Summary also works in CommonMark mode"
    }), "\n"]
  });
}

which is not the case for the mdx mode:

function _createMdxContent(props) {
  const _components = Object.assign({
    p: "p"
  }, props.components);
  return _jsxs("details", {
    children: [_jsx("summary", {
      children: "MD Summary"
    }), _jsx(_components.p, {
      children: "Our custom Details/Summary also works in CommonMark mode"
    })]
  });
}

I was able to make the details work in CommonMark by simply adding a lowercase details entry in the MDXProvider

slorber commented 1 year ago

Some elements like SEO <head> also seem quite critical to fix.

Unless we are able to fix all these critical elements fast, I think we can consider our CommonMark mode as "experimental" and eventually stabilize it in a further minor release. For v3 I think it's safer to keep the MDX parser by default even for .md files. Considering the CommonMark mode is new, that shouldn't be a problem for the community to adopt this mode incrementally.

Airkro commented 10 months ago

In my case, I make a remark plugin to using directive :docusaurus-doc-card-list to make <DocCardList /> work in docusaurus v3 CommonMark mode.

Maybe all the features can be landing as directive.

antoinetissier commented 5 months ago

Hi @slorber,

It seems to me that diff and bash code blocks are not properly highlighted with CommonMark. Is this something that you have observed as well ?

slorber commented 5 months ago

@antoinetissier most likely unrelated (unless proven with a repro), it's v3 that requires to declare these languages.

https://docusaurus.io/docs/migration/v3#prism-react-renderer-v20

CleanShot 2024-04-11 at 19 49 41

antoinetissier commented 5 months ago

I had missed that, thank you !