Skip to content
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

Generated site does not work with local file:// access #387

Closed
thomask77 opened this issue May 9, 2018 · 14 comments
Closed

Generated site does not work with local file:// access #387

thomask77 opened this issue May 9, 2018 · 14 comments

Comments

@thomask77
Copy link

I have a project where documentation is used in the field, and an internet connection is often not available. Starting a local web server is also not an option. Most likely the documentation will be shipped on a USB stick or CD-ROM.

Therefore, all links must be relative and point to ./foo/index.html instead of just ./foo

mkdocs does have a config option for this use case:

http://www.mkdocs.org/user-guide/configuration/#use_directory_urls

Is it possible to configure vuepress in the same way?

@ulivz
Copy link
Member

ulivz commented May 10, 2018

Sorry I cannot know what's your question. If you need help, please DON'T ignore the issue template, and provide a reproduced repo anyhow.

@ulivz ulivz closed this as completed May 10, 2018
@ycmjason
Copy link
Contributor

Not sure if it will work, but try setting base to .? 😂😂

@thomask77
Copy link
Author

@ulivz: Sorry for the lack of information. Here it is:

  • Your OS: Xubuntu 18.04
  • Node.js version: v10.0.0
  • VuePress version: 0.8.4
  • Browser version: Firefox 59.0.2 (or chromium-browser 65.0.3325.181)
  • Is this a global or local install: global
  • Which package manager did you use for the install: npm

Steps to reproduce:

mkdir bug387 
mkdir bug387/subdir
cd bug387

echo "# Link to [subdir](subdir)" > README.md
echo "# Subdirectory page" > subdir/README.md

vuepress build

cd .vuepress/dist

firefox index.html    # or chromium-browser for that matter

Results:

  • Scripts and CSS not loading, page not displaying correctly.
  • Link to subdir not working (points to subdir instead of subdir/index.html)

Expected:

  • Page fully loading and link working, like when served over http.

Use case:

I want to generate static docs that can be shipped on an USB stick, and can be viewed
by clicking on index.html (without internet access or a local HTTP server).

By manually editing the links in the HTML, I can get it to work.
Only thing missing is a config option like mkdocs' use_directory_urls.

@ycmjason:

After echo "module.exports = { base: '.' }" > .vuepress/config.js:

  • Assets now load for the main page, but not for subdir.
    The asset URLs miss a "../" when loading from subdir/index.html
  • Opening index.html now leads to a (correctly styled) "404" page.

Can you please reopen the bug?

@ycmjason
Copy link
Contributor

Try ./ then?

@thomask77
Copy link
Author

thomask77 commented May 10, 2018

Exactly the same as above. Asset URLs in subdir refer to "./assets/xxx", when "../assets/xxx" would be correct.

@meteorlxy
Copy link
Member

It could be a bug. I remember that publicPath coulde be set to an empty string, and the urls would be assets/xxx

@meteorlxy
Copy link
Member

meteorlxy commented May 10, 2018

I find it, it could be a bug of vue-server-renderer

https://github.com/vuejs/vue/blob/2efc0446b3ac1f18fff8b59215e7b60d51c41965/src/server/template-renderer/index.js#L107

https://github.com/vuejs/vue/blob/2efc0446b3ac1f18fff8b59215e7b60d51c41965/src/server/template-renderer/index.js#L184

href="${this.publicPath}/${file}"
src="${this.publicPath}/${file}"

So there will always be a / even if the webpackConfig.output.publicPath is empty

@meteorlxy
Copy link
Member

Issue submitted

@thomask77
Copy link
Author

Has this bug been fixed yet?

Please re-open!

@dgfreecodecamper
Copy link

This has been my experience trying to get this to work using the following files...
.vuepress/config.js

module.exports = {
    // using the full path instead of relative path
    // this can be changed to the folder to host the static files
    base: '/full/path/to/project/.vuepress/dist/'
}

README.md

# homepage

[page2](./page2.md)

## subtitle

Lorem ipsum dolor sit amet, alterum volumus pro ut

page2.md

# page2

[home](./README.md)

## another subtitle

After vuepress build all the pages other than index.html will load and display correctly. The full path has been set in base. Similarly any links to subheadings will work on the other pages but not on the index.html page. Loading the generated static site from the file system would require that the URL include /path/.vuepress/dist/index.html and when linking to subheadings also requires the index.html within the URL e.g. /path/.vuepress/dist/index.html#subtitle.

Any ideas??

@thorny-thorny
Copy link

I did a thing :D vuepress-offlinify

@z008hy
Copy link

z008hy commented Dec 25, 2020

You can set base to a absolute path

`
// .vuepress/config.js

const basePath = process.env.Node_ENV === 'production' ? path.resolve(__dirname, './dist') : '/';

module.esport = { title: '', base: basePath}

`

@rickalex21
Copy link

rickalex21 commented May 5, 2021

UDPATE: I tried everything in the comments and nothing worked. Opened up #2844

Vuepress is great If you want something that works out of the box and want to get online quickly but I haven't tried it offline 'yet'. I hope that there is an easy solution to this since I do have documentation that I don't want to make available online?

@wuliang142857
Copy link

I code a tool like this:

const path = require("path");
const fs = require("fs");
const cheerio = require("cheerio");
const walk = require("walk");
const isAbsoluteUrl = require("is-absolute-url");
const isUrl = require("is-url");

const distPath = fs.realpathSync(process.argv[2]);

const walker = walk.walk(distPath, {
    followLinks: false
});

walker.on("file", (root, fileStats, next) => {
    const extName = path.extname(fileStats.name);
    if (extName !== ".html") {
        next();
        return;
    }
    const htmlFile = path.join(root, fileStats.name);
    console.log(`Offline ${htmlFile}`);
    offlineFile(htmlFile);
    next();
});

walker.on("errors", (root, nodeStatsArray, next) => {
    next();
});

walker.on("end", () => {
    console.log("All Completed");
});

function offlineFile(fileName) {
    const htmlContent = fs.readFileSync(fileName, "utf-8");
    const $ = cheerio.load(htmlContent);
    // CSS
    $("link").each((index, element) => {
        const attributeValue = $(element).attr("href");
        const realAttributeValue = path.join(distPath, attributeValue);
        const relativeValue = path.relative(path.dirname(fileName), realAttributeValue);
        $(element).attr("href", relativeValue);
    });
    // JS
    $("script").each((index, element) => {
        const attributeValue = $(element).attr("src");
        const realAttributeValue = path.join(distPath, attributeValue);
        const relativeValue = path.relative(path.dirname(fileName), realAttributeValue);
        $(element).attr("src", relativeValue);
    });
    // a.href
    $("a").each((index, element) => {
        const attributeValue = $(element).attr("href");
        if (isUrl(attributeValue)) {
            return;
        }
        let realAttributeValue = path.join(distPath, attributeValue);
        if (fs.existsSync(path.join(realAttributeValue, "index.html"))) {
            realAttributeValue = path.join(realAttributeValue, "index.html");
        }
        const relativeValue = path.relative(path.dirname(fileName), realAttributeValue);
        $(element).attr("href", relativeValue);
    });
    // img
    $("img").each((index, element) => {
        const attributeValue = $(element).attr("src");
        if (isAbsoluteUrl(attributeValue)) {
            return;
        }
        if (isUrl(attributeValue)) {
            // replace like //example.com/1.png
            $(element).attr("src", `https:${attributeValue}`);
        } else {
            const realAttributeValue = path.join(distPath, attributeValue);
            const relativeValue = path.relative(path.dirname(fileName), realAttributeValue);
            $(element).attr("src", relativeValue);
        }
    });
    
    const transformedHtml = $.html();
    fs.writeFileSync(fileName, transformedHtml, "utf-8");
}

Run it like this:

node offline.js dist

Some dependencies should be add firstly:

yarn add -D cheerio walk is-absolute-url is-url

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants