-
-
Notifications
You must be signed in to change notification settings - Fork 8.8k
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
Allow referencing markdown links from the repository root #4039
Comments
I understand such motivation but at the same time using relative links is advised for 2 reasons:
Also, a Docusaurus site is not "aware" of the repository root, and you might use Docusaurus without a repository anyway. My suggestion would be to support absolute file paths resolved from the docs version root, as it would at least keep working with versioning (but breaks github UI nav), and is easier to maintain.
Does it make sense? |
A leading slash on Github corresponds to repo root. https://github.com/vjpr/readme-github-symlink-test/tree/master/docs
If you use multiple docs plugins, won't each plugin have their own versioning? I would only use absolute paths for linking to other plugins.
For me, keeping IDE navigation working is pretty important. I use the Markdown Navigator plugin for WebStorm and it the links to be refactored when they are moved around. Relative paths do work with this though. Would be great if the |
Just posting a tree to clarify my setup.
|
I see. Still not sure we should couple Docusaurus behavior to Git/GitHub specificities. Some might use docusaurus with a FTP or SVN or Mercurial as well
You can't link from instance1 to instance 2 with relative paths for that reason. A docs instance is sandboxed and does not know about the docs and slugs of another version (or even other plugins like blog and pages). Using relative or absolute md file paths, a plugin should only reference md docs of the same plugin, not from other plugin's folders. We could maybe allow providing a list of paths from which to resolve the md files, so that your absolute links above would resolve fine (as long as they reference files of the same plugin instance). You'd just have to add something like Can this work for your usecase? I'm not sure because you seem to want cross-plugin paths to work according to your FS structure example, and we currently don't support that. Plugin1/doc1.md has no way to figure out how to replace a markdown link path to Plugin2/doc2.md by a concrete url, as the 2nd plugin has its own custom logic to create that URL. That's something we would try to support but it would require some infra in core first so that each plugin can somehow register to core its md->URL resolution mapping, making this data accessible globally. |
So the monorepo use case would be if you had a top-level docs plugin for your repo, and you wanted to link to the docs for all the open-source packages you have.
I agree that docs instances should be sandboxed, but the link resolution should be configurable. I have included a remark plugin workaround further down. But I would rather not use a plugin and just have a function I can pass in allowing me to transform links (with parameters of the build environment maybe).
This would be a nice addition for sure. But it doesn't solve the cross-plugin paths.
Yeh this is what I am looking for. I was able to hackily work around it by creating the following remark plugin: remark-docusaurus-monorepo-refsvar visit = require('unist-util-visit')
var toString = require('mdast-util-to-string')
const findUp = require('find-up')
const path = require('path')
const repoRoot = path.dirname(findUp.sync('pnpm-workspace.yaml'))
const findWorkspacePackagesSync = require('get-workspace-pkgs-sync')
// Get all workspace packages in monorepo.
const pkgs = findWorkspacePackagesSync(process.cwd(), {cached: true})
// Filter packages that have Docusaurus docs.
let docusaurusPkgs = pkgs.filter(p => p.manifest.live?.docusaurus?.enable)
// Obtain the docusaurus plugin id (which becomes the slug of the plugin root)
// using the same recipe as is used to create it when configuring the plugin.
docusaurusPkgs.map(pkg => {
pkg.docusaurusId = idFromPackageName(pkg.manifest.name)
})
// Convert references to Docusaurus URLs/slugs.
module.exports = opts => {
// DEBUG
//console.log(JSON.stringify(docusaurusPkgs, null, 2))
return transform
function transform(tree, vfile) {
// Get the filename of the current file being processed.
const filename = vfile.history[0]
// Assign a visitor function for every markdown link found. I.e. `[foo](/foo)`.
visit(tree, 'link', visitor)
function visitor(node) {
// a. URLs.
if (node.url.startsWith('http://')) return
// b. Abs paths.
if (node.url.startsWith('/')) {
// Resolve to repo root.
node.url = path.join(repoRoot, node.url)
return
}
// c. Rel paths.
// Resolve relative to file.
// Get absolute path on disk.
const absDiskPath = path.resolve(path.dirname(filename), node.url)
// We must avoid nested docs paths.
// Find all packages with roots that contain this absolute disk path.
const dps = docusaurusPkgs.filter(pkg => absDiskPath.startsWith(pkg.dir))
// We choose the longest path.
const docsRoot = longestDir(dps)
// --
// Replace path with repo root relative path.
node.url = path.join(
docsRoot.docusaurusId,
absDiskPath.replace(docsRoot.dir, '').replace(/.mdx?/, ''),
)
}
}
}
////////////////////////////////////////////////////////////////////////////////
function idFromPackageName(pkgName) {
// @live/foo-bar.baz => live_foo_bar__baz
return pkgName
.replace('@', '')
.replace(/-/g, '_')
.replace('/', '_')
.replace(/\./g, '__')
}
////////////////////////////////////////////////////////////////////////////////
var longestDir = arr =>
arr.reduce(function (a, b) {
return a.dir.length > b.dir.length ? a : b
}) I would prefer to avoid this by having a function to transform markdown links as mentioned earlier. Also, maybe some built-in helper function that takes a path and returns and url for the plugin instance that contains it. In my code above I simply look for the closest package.json file and check whether it has a docs plugin (custom monorepo logic though). |
GitHub does this, because there's no sense of "file system" on GitHub. However, these Markdown file links beginning with a slash are already well-defined. They are absolute file paths, for example, |
🚀 Feature
Have you read the Contributing Guidelines on issues?
Yes
Motivation
In a monorepo setting with multiple docs plugins, you may want to link between two sites.
For example I write:
packages/lib1/docs/readme.md
And I get this error:
In my IDE, I can cmd+click on the link
Pitch
Relative links would solve this but its painful to keep up to date.
Maybe allow a config option to control the linking behaviour.
The text was updated successfully, but these errors were encountered: