-
-
Notifications
You must be signed in to change notification settings - Fork 8.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
TOC does not work when importing one MDX into another #3915
Comments
This usage should be supported, but it's a current limitation of the existing system. Unfortunately, I'm not sure how to implement this technically, and still busy on i18n. In the meantime I'd recommend to only put raw text in mdx and duplicate the headings. That's not ideal but I don't have any other solution for now 😓 You could also add a build script that copy a file to multiple locations, or use a remark plugin that substitute a placeholder with a content string in multiple docs |
How difficult would it be to fix? I could possibly put up a PR |
@oriooctopus unfortunately I suspect this to be quite complex to implement, and can't even give you much help to do so because I'm not sure how this should be done. You can look at the code in this folder: packages/docusaurus-mdx-loader/src/remark/toc |
@slorber I think we can address this by getting docusaurus-mdx-loader to follow jsx tags into their imported sources when traversing the AST. I did something similar to this before, using the The only downside in my eyes is that we'd be using the node fs api, which means this package wouldn't work at runtime in the browser anymore (if it does now). Do you think this would be an acceptable change? |
Yes @jknoxville this is what I have in mind: a recursive visitor that is able to "flatten" the TOC structure of multiple MDX docs (and preserve the correct TOC ordering). This code already runs in node (it's a Webpack loader) |
@jknoxville do you still have any interest in fixing this? If not, maybe we could sync on what you had in mind and I might be able to implement it? |
@oriooctopus I'm interested, but it's not top of my queue right now, so feel free to take a stab! Here's a prototype I made a while ago, for a remark plugin that effectively re-implements mdx transclusions by parsing the target of any imported markdown files, and then replacing any JSX nodes that use it, with the nodes of the target AST. It's scrappy, and not production-ready (currently uses eval for one thing - I'd recommend using babel to parse the imports instead), but it works. Maybe there's a more elegant way to do it. What I imagine, is modifying search.js to do what that prototype does before it starts visiting headings to assemble its TOC. I haven't tried this, but don't see why it wouldn't work. |
if that helps I remembered that Gatsby has a way to extract all imports/exports from MDX. |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
@Laptopmini what I understand is that you want to create a TOC dynamically from data fetched from an API. This is unrelated to the current issue which is about importing one MDX doc inside another. Please open another issue if you want to discuss dynamically generated TOC, and let's keep this issue focused on its initial problem. I believe you could just swizzle the TOC component and add your stateful logic here. |
Hi @slorber -- Thanks for your reply. So I have a file that defines a number of configuration variables that are common to several environments, so I have a single doc that I am importing into the other docs, but I need each of the variables to be included in the floating TOC, which they are not, as clearly confirmed by this issue. I see from your earlier response that fixing this issue is not a priority for docusauraus right now -- do you know if it will be at any point in the near roadmap? Are there any viable workarounds (the gatsby plugin you mention, for example)? Manually adding a header for each variable is not viable for my content. It would defeat the purpose of the transclusion. Thank you for any advice! |
Any solution for this? @slorber @oriooctopus |
I have not heard of any updates to this issue yet, @khushal87. I did throw in a feature request at https://docusaurus.canny.io/feature-requests/p/include-transclusion-content-headings-in-toc so please feel free to vote it up so we can get this on the roadmap at least! :) |
Done, hope to get this soon. @sweeneyskirt-sl 🤞 |
Some related notes:
|
Wonderful. I needed the target file combining the partials to show the right sidebar. Because of this bug, I have decided to take a somewhat circuitous route of adding the |
Any news on this subject? |
Seems like we are waiting for @dimaMachina to create a remark plugin with his fix. |
Yes! Sorry, currently I am busy with Nextra 3 release and future speak in Amsterdam on 8 November, I hope to do it next month ✌️ |
I think we just ran into this as well. We basically wanted to have a component that renders a small label next to a heading to note if the thing being discussed is a beta item or not. While the component works flawlessly, the TOC does not render the heading. As a workaround, for now is there a way to manually create a TOC for a given MD doc? |
This is how I did it. Quite sure there are better ways. I split the Markdown document I wanted to import into multiple MDX files. Each MDX file contains only the content from a specific section of the Markdown doc. So in the below, my MD doc had sections like Description, Parameters and Returns in one doc. After splitting it and saving into multiple files, each beginning with the underscore character, I imported them into another MDX doc like this. This way, Docusaurus displayed all the section headers, like it would for any normal MD doc.
|
We've done it like this
But then you can't mix it with other headers, like this
|
I submitted a PR for Docusaurus v2, that I'll be willing to work on, but in the meantime, until it is accepted, I made a quick drop in replacement remark plugin that fixes this behaviour: It implements the logic from shuding/nextra#2199. |
This has been fixed (main/canary) as part of #9684, and will be released in Docusaurus v3.2 Thanks for the inspiration @dimaMachina and the initial port @anatolykopyl 🤗 |
Nice feature, do you plan to also support headings from custom JSX/TSX components to appear in ToC ? I have a React component that reads a JSON file and create headings and paragraphs based on it (the JSON file is loaded as a module but I guess it means the ToC should be generated dynamically at runtime and not at compile time?) |
@jbltx we only support importing other MDX files atm However, it could be technically possible to also support React imported components, and try to get the compiler to output something looking like this: import Partial,
{toc as __tocPartial} from "_partial.mdx"
import MyComponent from "MyComponent"
# Doc
## Doc heading
<Partial/>
<MyComponent/>
export const toc = [
{
"value": "Doc heading",
"id": "doc-heading",
"level": 2
},
...__tocPartial,
...MyComponent?.toc?.()
] Note that in any case, it would be your responsibility to implement the const MyComponent = () => <h2 id="hello">Hello</h2>
MyComponent.toc = () => {
return [{id: "hello", value: "Hello", level: 2}];
};
export default MyComponent; We can't execute the React code and infer the TOC from that execution. Would that be a helpful addition, or is this too limited? |
Thank you for the suggestion @slorber, I think your example is enough for my use case indeed! 👍 |
I don't know if I'm doing something wrong, but this is still not working for me, even after the fix:
## Release {props.release}
import Release from "./_release.mdx"
# Releases
## Top heading
{["v1", "v2", "v3"].map((release) => <Release release={release} />)} And the result: |
@felipecrs this is unlikely we will ever support this. The TOC is computed statically at MDX compilation time. We are not running the JS to see what the output is and if it contains any heading. Hence we don't support such loop, nor using props inside partial headings. If you want that, you'd have to use the TOC function form described just above, a possible enhancement that we haven't implemented yet. |
@slorber I see. Implementing my own |
Ops, sorry, did you mean that I could already implement my I tried it with: import Release from "./_release.mdx"
# Releases
## Top heading
{["v1", "v2", "v3"].map((release) => <Release release={release} />)}
export const toc = () => ["v1", "v2", "v3"].map((release) => ({
"value": `Release ${release}`,
"id": `release-${release}`,
"level": 2
})) And then the toc disappeared entirely. (Also tried |
@felipecrs we don't support a toc function yet, only a toc array export. You should rather do that instead of a loop import ReleaseV1 from "./_releaseV1.mdx"
import ReleaseV2 from "./_releaseV2.mdx"
import ReleaseV3 from "./_releaseV3.mdx"
# Releases
## Top heading
<ReleaseV1/>
<ReleaseV2/>
<ReleaseV3/> Note, we don't support "dynamic headings" such as |
Great. Thank you, I'll watch the pull request, because my data is very dynamic so I can't define them statically. |
According to facebook#3915 (comment) the issue is fixed.
🐛 Bug Report
On our site we have a couple of duplicate doc pages. To avoid repeating content we have one doc as the source of truth then import the content like so:
The issue is, the table of contents is not picked up on the pages that import the content. Please let me know if there is a better way to handle duplicate pages and if this usage is just conceptually wrong
Have you read the Contributing Guidelines on issues?
Yes
To Reproduce
npx @docusaurus/init@latest init my-website classic
in doc2:
It's worth noting that this also happens on my 6 month old version, so I don't think that it's due to anything recent
The text was updated successfully, but these errors were encountered: