-
-
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
Support Relative Path #448
Comments
@huchenme Hi. What error do you get when you use |
@JoelMarcey After running |
@huchenme Hi. Do you have a repo I can look at to see your |
Hi @JoelMarcey , I have just created this repo https://github.com/huchenme/docusaurus-demo It is generated from
and click Docs header, you should able to see the error. and then try run If you guys are busy, I can work on it and send a PR, is that ok with you? |
I think this is the same feature request: "Make the built site work without a web server" Expected behaviour: You can navigate through pages and docs and links work |
It would be really nice if this was supported. I just save my build artifacts on circle ci but the site will not work since it doesn't handle relative Problems seem to be that in the generated html files css and images are referenced as
when it should have been
since they are relative to their html file. Using the |
The problem I ran into was I want to deploy to docs to both |
Would be great feature as its quite painful to review build on local machine |
@endiliey - you haven't done anything around this for the next version of Docusaurus, right? I know we had #864 for static asset. If not, could we employ something similar to what was done in KaTeX/KaTeX#1525, but within the core instead of siteConfig? |
This would be a nice feature addition. It would enable users to download an offline zip of the website, open For example, I'm using docusaurus for documenting Scala projects https://olafurpg.github.io/sbt-docusaurus/ I also release the documentation as a zip file to Maven Central (similar to npm) and it's possible to browse those docs and download offline archives via https://www.javadoc.io/. Currently, the css/js/html artifact links return 404s when browsing sbt-docusaurus docs on https://static.javadoc.io/com.geirsson/sbt-docusaurus-docs_2.12/0.1.1/sbt-docusaurus/docs/installation.html I could work around this problem by generating the site with baseUrl |
A workaround for this issue is to post-process the anchor links in the html files generated by
None of these transformations are Docusaurus-specific, they can be applied to any static site. I would not be surprised if there already exists a JavaScript library that can do this (more robustly than me 😅 ). The benefit of relative links is that
|
Relative paths make deployments really simpler. It would be great to support them in a future release. In the meantime, here's how you can transform absolute links to relative ones in a postbuild script: // utils.js
const path = require('path');
const fs = require('fs-extra');
const recursiveReaddir = require('recursive-readdir');
const baseUrlPattern = '/_baseUrlPattern_/';
const baseUrlRegExp = new RegExp(baseUrlPattern, 'g');
const buildDirectory = path.join(__dirname, 'build');
const relativify = (content, filePath) =>
content.replace(baseUrlRegExp, () => {
const result = `${path.relative(`${path.dirname(filePath)}`, '')
// Normalize Windows path separators to Unix ones
.replace(/\\/g, '/')}/`;
return result === '/' ? '' : result;
});
const websiteTextualFileExtensions = ['.css', '.js', '.html', '.xml'];
const isNotWebsiteTextualFile = (filePath, stats) =>
!(stats.isDirectory() || websiteFileTextualExtensions.includes(path.extname(filePath))));
const postProcess = async () => {
const filePaths = await recursiveReaddir(buildDirectory, [isNotWebsiteTextualFile]);
await Promise.all(
filePaths.map(async filePath => {
const content = await fs.readFile(filePath);
const relativePath = path.relative(buildDirectory, filePath);
await fs.writeFile(filePath, relativify(String(content), relativePath));
})
);
};
module.exports = {
baseUrlPattern,
postProcess,
}; // siteConfig.js
const {baseUrlPattern} = require('./utils');
const isBuilding = process.env.npm_lifecycle_script
&& process.env.npm_lifecycle_script === 'docusaurus-build';
const siteConfig = {
// Keep `/` in watch mode.
baseUrl: isBuilding ? baseUrlPattern : '/',
// ...
};
module.exports = siteConfig; // postprocess.js
'use strict';
require('loud-rejection/register');
const {postProcess} = require('./utils');
postProcess(); // package.json
{
"devDependencies": {
"docusaurus": "1.6.2"
},
"scripts": {
"build": "docusaurus-build",
"postbuild": "node postprocess"
}
} |
Any update available on this item? This would allow me to have a review site deployed very easily. I can deploy the site in a different path other than what's mentioned in |
@JoelMarcey @yangshun - Would you be able to provide some feedback? If I can I'd love to look into implementing this and submit a PR for it. |
@amimas Sure, go ahead 😄 |
Any guidance available? I'm new to this and not really sure where to begin. |
I think at this point our architecture relies a lot on baseUrl and supporting this will be quite a huge refactor. I personally feel the effort is better spent elsewhere Sent with GitHawk |
I agree with you @endiliey, I wanted to provide an easy way to check the requirement is complete, it's not that I use it with file:// We generate the documentation site as an artifact on the CI and it stores and serves it for us. The builds have auto-generated ids so we don't know the final url in advance. Of course you know where to put the effort, thanks a lot for the great work :D |
To echo @jacarma 's comment, our primary use-case is also to host Docusaurus sites at URLs we don't know in advance. For example, here is a 3rdparty service that is hosting our Docusaurus documentation for every published version of a library we maintain https://www.javadoc.io/doc/org.scalameta/munit-docs_2.12/0.4.3/index.html |
@endiliey That is your view based on 12 years old article and a couple of false information. |
@endiliey Sorry - the whole security in a browser is about running a browser safely on a local machine AND on the web. This is how browsers worked since they were invented. |
All - I find it surreal that I was looking at this closed issue less than 24 hours ago and all of a sudden it started gaining traction with comments again. That said, I just want you to be aware, in case you didn't know, that @endiliey passed away earlier this year after a long battle with cancer. https://docusaurus.io/blog/2020/01/07/tribute-to-endi He really gave maximum effort to this project, and I want him to be remembered for that. |
@JoelMarcey That's really, really sad to read... :( |
RIP. |
My most sincere condolences |
My condolences to Endi's family and friends. Given that this is still a very valuable feature, do the new maintainers have any plans for it? |
@tibdex - Your solution is quite elegant and works for the most part of it. However the webpack script in |
I improved @tibdex approach by resolving all nested paths in a single @roguexz I think this approach should also work fine with Webpack too, but I didn't manage to test it yet. ✌️ // postprocess.js
'use strict';
const fs = require('fs-extra');
const path = require('path');
const recursiveReaddir = require('recursive-readdir');
const buildDirectory = path.join(__dirname, 'build');
const absoluteUrlRegExp = /(href|src)="(?!http[s]|ftp?:\/\/)([^"|#]+)"/g;
const isDirectory = dirPath => path.extname(dirPath) === '';
const convertAbsolutePathsToRelative = (content, filePath) =>
content.replace(absoluteUrlRegExp, (_absoluteUrl, $1, $2) => {
const currentDirPath = path.dirname(filePath);
const relativeDirPath = currentDirPath === '.' ? '.' : path.relative(currentDirPath, '');
let relativePath = path.join(relativeDirPath, $2);
if (isDirectory(relativePath)) {
relativePath = path.join(relativePath, 'index.html');
}
return `${$1}="${relativePath}"`;
});
const websiteTextualFileExtensions = ['.css', '.js', '.html', '.xml'];
const isNotWebsiteTextualFile = (filePath, stats) =>
!(stats.isDirectory() || websiteTextualFileExtensions.includes(path.extname(filePath)));
const postProcess = async () => {
const filePaths = await recursiveReaddir(buildDirectory, [isNotWebsiteTextualFile]);
await Promise.all(
filePaths.map(async filePath => {
const content = await fs.readFile(filePath);
const relativePath = path.relative(buildDirectory, filePath);
await fs.writeFile(filePath, convertAbsolutePathsToRelative(String(content), relativePath));
})
);
};
postProcess(); // package.json
{
"scripts": {
"build": "docusaurus build",
"postbuild": "node postprocess"
},
"devDependencies": {
"@docusaurus/core": "^2.0.0-beta.5"
}
} |
Everyone, this is a quite old issue that was first opened for Docusaurus v1. For deploying Docusaurus v2 site to multiple environments with different baseUrls, please use For deploying a Docusaurus v2 site without a server, using the |
Since we are slowly approaching the holy grail of handling the assets without hardcoding URLs in some envs... which is terrible for maintenance, I will add 2 cents. It would be great to have possibility of setting baseUrl (the part that is used in javascript) during runtime just like webpack does it. Its possible that it would require splitting it into two variables (one for site url, one for assets url), but from my experience with static site generators, cdns, documentations, it is a great feature that makes docs developers life easier. |
@ohkimur: Thanks for the plugin! Script references stilll need adjusted, those may require @slorber: Where would you enter |
You have to set it as an env variable outside of docusaurus, in your CI/CD config, in your bashrc or when running CLI commands like |
Thank you, that makes sense. So this approach would not fill in the final filesystem location once the build is deployed, but it can be used if the final destination is known in advance. When a build needs to be deployed locally, I could see the compiled files reference a location variable like window.location (or, in the case of electron, a process variable) that's unique to each machine and fill in baseUrl that way. But those won't be defined during the compilation step, so they would somewhat have to be added (and tested) separately. |
@larissa-n @slorber I know about this issue. Isn't quite clear for me at the moment how to replace the paths in scrips in an elegant way, that's why I didn't fix this problem yet. If you have any suggestions I am open. |
@ohkimur Thank you for posting your example code, helped me out greatly. Real shame docusaurus isn't focused on issues like this one. Seems to be a really common feature people are after. |
This works superbly, but for one thing. It doesn't support mode switching (I get the disabled icon). But if I copy the build to a test server, mode switching works. Cheers. |
Please note this issue was initilly opened for Docusaurus v1 in 2018. Since then, Docusaurus v2 has been released. It's a full rewrite and has nothing to do with the v1 codebase. Mixing comments for Docusauru v1 and Docusaurus v2 here is confusing so I'm going to lock this issue. There are other Docusaurus v2+ issues to comment on now, like this one: #3825 If being able to browser a Docusaurus v2 site offline with the
@ColinLondon this probably doesn't work as well as you think. If the theme switch is disabled it likely means React couldn't hydrate on your page, and thus all interactive elements will not work. These things are all likely to be broken:
So... no this is not a good solution, unless you are ok with the tradeoffs of having all these elements not working... |
Docusaurus expect
baseUrl
to be absolute path, to use relative path, I have tried to putbaseUrl=''
and it does not work fordocs
link and generated build.It will be nice that Docusaurus support relative mode as well
The text was updated successfully, but these errors were encountered: