-
-
Notifications
You must be signed in to change notification settings - Fork 8.5k
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
Feature: referencing variables from markdown pages (placeholder substitution) #395
Comments
Interesting idea. We did something similar for nuclide.io using JS and referencing the package.json file. I think this is something that could definitely be implemented for some upcoming version of Docusaurus. |
That would be an awesome feature! Julen mentioned "version numbers, URLs, etc." but it would also be great to insert automatically computed markup from JSDoc for instance. Thus, if you decide to implement it, it would be nice to support the injection of Markdown (or HTML) markup and not only scalar values. |
HI, @JoelMarcey I am planning to take this after finishing #694 but I think I will work with scalar values first. Is that okay? |
@gedeagas Sounds great! I think this is a feature that can be done in increments. |
Isn't this another thing best left to markdown plugins? |
Ok, but just to be clear: that plugin will not be included as a dependency of Docusaurus, right? It would be configured by users in their I'm just a bit confused by the fact that this is a feature request for Docusaurus when nothing actually needs to change in Docusaurus for this to be supported |
Here's how variable injection can be done: Put this in const {Plugin: Embed} = require('remarkable-embed');
// Our custom remarkable plugin factory.
const createVariableInjectionPlugin = variables => {
// `let` binding used to initialize the `Embed` plugin only once for efficiency.
// See `if` statement below.
let initializedPlugin;
const embed = new Embed();
embed.register({
// Call the render method to process the corresponding variable with
// the passed Remarkable instance.
// -> the Markdown markup in the variable will be converted to HTML.
inject: key => initializedPlugin.render(variables[key])
});
return (md, options) => {
if (!initializedPlugin) {
initializedPlugin = {
render: md.render.bind(md),
hook: embed.hook(md, options)
};
}
return initializedPlugin.hook;
};
};
const siteVariables = {
scalar: 'https://example.com',
// Since the variables are processed by Docusaurus's Markdown converter,
// this will become a nice syntax-highlighted code block.
markdown: [
'```javascript',
'const highlighted = true;',
'```',
].join('\n'),
// We can use HTML directly too as HTML is valid Markdown.
html: [
'<details>',
' <summary>More details</summary>',
' <pre>Some details</pre>',
'</details>'
].join('\n')
};
const siteConfig = {
markdownPlugins: [
createVariableInjectionPlugin(siteVariables)
],
// rest of the config
};
module.exports = siteConfig; Then, in one of the doc page, write: ## Scalar injection
{@inject: scalar}
## Markdown injection
{@inject: markdown}
## HTML injection
{@inject: html} And this is what Docusaurus would render: As you can see, by leveraging remarkable-embed, the implementation of the custom plugin for variable injection is quite small. I'm not even sure it's worth making a dedicated npm package out of it. The only drawback I can see is that the injected markup isn't pre-processed by Docusaurus. For instance, if one of the variables contains a Markdown title such as |
Awesome @tibdex. |
This is really sweet tibdex...it is not replacing variables that are inside of a markdown code block though. I guess those are kind of regarded as literals but as I might want some code to depend on a variable, is there anything I should do? Edit: also realized the original post requests having this feature available in code blocks |
This issue is closed due to stale activity. If you think there is a need for it, please open up a new issue with new template. |
First of all, thanks @tibdex for this plugin example ! |
An option is to preprocess the markdown files outside of Docusaurus. You can develop a pipeline that reads the unprocessed markdown files from another directory, process them, write them to the Docusaurus's markdown files directory, and then build your website with Docusaurus. |
Is there any official way to reference variables in v2? |
What type of variables are you trying to reference? |
Hi @JoelMarcey, I want to declare a global javascript variable, say |
Yeah you can write JS in MDX so you can import anything and use variables. |
https://v2.docusaurus.io/docs/markdown-features @anidotnet See if you can get that to work, and, if you are so inclined, you could send a pull request to update the documentation to talk about how to make it work. |
Hi @JoelMarcey thanks. But I never used react and a newbie in js world. So if I write my version in a .env file like VERSION=1.0 or write it in a version.js file at the root of the project like export const siteVariables = {
versionNumber: '1.0.0'
}; how do I use any one of these in an mdx file? Mainly I am trying to replace a javascript variable in a code block like
Any help would be highly appreciated. |
I don't know if you can use variables within the markdown syntax (fenced code blocks), but you can use it within JSX. import {siteVariables} from '@site/src/versions';
// ...
<Tabs
groupId="installation"
defaultValue="java"
values={[
{ label: 'Java', value: 'java', },
]
}>
<TabItem value="java">
// Cannot use Markdown syntax here
<code>compile 'mylib:mylib:{siteVariables.versionNumber}'</code>
</TabItem>
</Tabs> |
The planned Track this issue: #5568 |
@Zenahr thanks for providing this example. Is there a way to get remark plugins to process content in code blocks? |
@JakeSCahill yeah I think so. Haven't done it myself but you can check the official docusaurus-admonitions-plugin source. They do something with code blocks. |
For anyone who's interested, you can provide the const visit = require('unist-util-visit');
const plugin = (options) => {
const transformer = async (ast) => {
visit(ast, ['text, 'code'], (node) => {
// Replace all occurrences of VAR::varName with the value of varName
node.value = node.value.replace(/VAR::([A-Z_]+)/g, (match, varName) => {
return options.replacements[varName] || match;
});
});
};
return transformer;
};
module.exports = plugin; |
In case you want to make it work for links: const visit = require('unist-util-visit');
const plugin = (options) => {
const transformer = async (ast) => {
visit(ast, ['text', 'code', 'link'], (node) => {
// Replace all occurrences of VAR::varName with the value of varName
let value;
switch (node.type) {
case "link":
value = node.url;
break;
case "text":
case "code":
value = node.value;
break;
}
value = value.replace(/VAR::([A-Z_]+)/ig, (match, varName) => {
return options.replacements[varName] || match;
});
switch (node.type) {
case "link":
node.url = value;
break;
case "text":
case "code":
node.value = value;
break;
}
});
};
return transformer;
};
module.exports = plugin; Note that you must install |
In theory this will stop the API docs thrashing on every build. Of course, there is a drawback in that if main changes but we haven't released a new version of the docs yet the links will go out of date. So longer term we might want to investigate some kind of variable where we can continue to have up to date revs but keep the rev in a single variable somewhere: facebook/docusaurus#395 In the meantime much smaller commits will be a relief
Fix all markdown links and configure the Docusaurus build to fail on broken links. Compared to before there are two main differences for links within Docusuaurus: * Links between URL links need to be URL links to be resolved. This will be fixed in Docusaurus 3 [1]. * Links that point to files outside the "docusaurus" directory need to be absolute links to be resolvable in the final website. This could mabye be improved by adding support for variables [2]. [1]: facebook/docusaurus#6370 [2]: facebook/docusaurus#395 Signed-off-by: Martin Nonnenmacher <martin.nonnenmacher@bosch.io>
Fix all Markdown links and configure the Docusaurus build to fail on broken links. Compared to before there are two main differences for links within Docusuaurus: * Links between URL links need to be URL links to be resolved. This will be fixed in Docusaurus 3 [1]. * Links that point to files outside the "docusaurus" directory need to be absolute links to be resolvable in the final website. This could mabye be improved by adding support for variables [2]. [1]: facebook/docusaurus#6370 [2]: facebook/docusaurus#395 Signed-off-by: Martin Nonnenmacher <martin.nonnenmacher@bosch.io>
Fix all Markdown links and configure the Docusaurus build to fail on broken links. Compared to before there are two main differences for links within Docusuaurus: * Links between URL links need to be URL links to be resolved. This will be fixed in Docusaurus 3 [1]. * Links that point to files outside the "docusaurus" directory need to be absolute links to be resolvable in the final website. This could mabye be improved by adding support for variables [2]. [1]: facebook/docusaurus#6370 [2]: facebook/docusaurus#395 Signed-off-by: Martin Nonnenmacher <martin.nonnenmacher@bosch.io>
Fix all Markdown links and configure the Docusaurus build to fail on broken links. Compared to before there are two main differences for links within Docusuaurus: * Links between URL links need to be URL links to be resolved. This will be fixed in Docusaurus 3 [1]. * Links that point to files outside the "docusaurus" directory need to be absolute links to be resolvable in the final website. This could mabye be improved by adding support for variables [2]. [1]: facebook/docusaurus#6370 [2]: facebook/docusaurus#395 Signed-off-by: Martin Nonnenmacher <martin.nonnenmacher@bosch.io>
Fix all Markdown links and configure the Docusaurus build to fail on broken links. Compared to before there are two main differences for links within Docusuaurus: * Links between URL links need to be URL links to be resolved. This will be fixed in Docusaurus 3 [1]. * Links that point to files outside the "docusaurus" directory need to be absolute links to be resolvable in the final website. This could mabye be improved by adding support for variables [2]. [1]: facebook/docusaurus#6370 [2]: facebook/docusaurus#395 Signed-off-by: Martin Nonnenmacher <martin.nonnenmacher@bosch.io>
Many thanks to @Zenahr and @alexandernst for the plugin! In testing the latest version posted I found that it doesn't work for |
Just adding support for AST node type |
@alexfornuto see below. const visit = require('unist-util-visit');
const plugin = (options) => {
const transformer = async (ast) => {
visit(ast, ['text', 'code', 'link'], (node) => {
// Replace all occurrences of VAR::varName with the value of varName
let value;
switch (node.type) {
case "link":
value = node.url;
break;
case "text":
case "code":
value = node.value;
break;
}
value = value.replace(/VAR::([A-Z_]+)/ig, (match, varName) => {
return options.replacements[varName] || match;
});
switch (node.type) {
case "link":
node.url = value;
break;
case "text":
case "code":
node.value = value;
break;
case "inlineCode": // <-- THIS HANDLES INLINE CODE BLOCKS.
node.value = value;
break;
}
});
};
return transformer;
};
module.exports = plugin; |
@Zenahr you probably also need to visit const visit = require(https://github.com/syntax-tree/unist-util-visit);
const plugin = (options) => {
const transformer = async (ast) => {
visit(ast, ['text', 'code', 'inlineCode', 'link'], (node) => {
// Replace all occurrences of VAR::varName with the value of varName
let value;
switch (node.type) {
case "link":
value = node.url;
break;
case "text":
case "code":
case "inlineCode":
value = node.value;
break;
}
value = value.replace(/VAR::([A-Z_]+)/ig, (match, varName) => {
return options.replacements[varName] || match;
});
switch (node.type) {
case "link":
node.url = value;
break;
case "text":
case "code":
case "inlineCode":
node.value = value;
break;
}
});
};
return transformer;
};
module.exports = plugin; |
Thanks, gents! I used @slorber's version FTW. This is my derp, as I tried doing the same thing but with |
In theory this will stop the API docs thrashing on every build. Of course, there is a drawback in that if main changes but we haven't released a new version of the docs yet the links will go out of date. So longer term we might want to investigate some kind of variable where we can continue to have up to date revs but keep the rev in a single variable somewhere: facebook/docusaurus#395 In the meantime much smaller commits will be a relief
Evening, @slorber. I'm not familiar with Javascript and would like to know how I could install your plugin. |
Sorry to disturb everyone here. I found a workaround after a long time searching. And it's not mentioned in the above comments. Maybe useful for somebody. The documentation is https://docusaurus.io/docs/api/docusaurus-config#preprocessor Here is an example of how to use it. https://gitea.com/gitea/docs/src/branch/main/docusaurus.config.js#L213 . This will replace all |
First of all, thanks for sharing and supporting Docusaurus! It's been pretty easy to get started.
I'm posting a feature request — I haven't found anything similar in the issue tracker so forgive me if it's been discussed before.
Motivation: sometimes docs need to reference information such as version numbers, URLs etc. and having them manually typed in the markdown pages is not ideal because this type of information often gets referenced multiple times.
Taking that into account, it would be great if Docusaurus supported passing variables into pages (from e.g.
siteConfig
). It already supports special Markdown markup via the<AUTOGENERATED_TABLE_OF_CONTENTS>
marker, and it could potentially do something similar for variables.For example, typing in
<VAR:projectName>
would get replaced with the value ofsiteConfig.projectName
. Ideally this works in code blocks too (```).The text was updated successfully, but these errors were encountered: