vuejs / vuepress

📝 Minimalistic Vue-powered static site generator
https://vuepress.vuejs.org
MIT License
22.49k stars 4.77k forks source link

Consider to allow to use alternative for public directory #1491

Open timaschew opened 5 years ago

timaschew commented 5 years ago

Feature request

What problem does this feature solve?

The problem is that images and other resources which are referenced in markdown files won't work any other environment (on GitHub, GitLab, local preview tools). Because the resources need to be placed into the .vuepress/public directory, but the URL won't include neither .vuepress nor public.
This is really weird.

// edit Also this will be much easier for everyone who is migrating to VuePress, for instance from GitBook.

What does the proposed API look like?

Allow to put images and other resources next to the markdown files instead of forcing to put them into .vuepress/public.

How should this be implemented in your opinion?

For the vuepress build command just passthrough all files which are have not a markdown file extension. This is the only file types you're expecting, right? Other files, like styles or vue components live somewhere else, so they are not affected.

Are you willing to work on this yourself?

Sure, let me know if you agree in general with this idea.

shigma commented 5 years ago

Allow to put images and other resources next to the markdown files instead of forcing to put them into .vuepress/public.

So you want to have a file structure as below:

docs
  .vuepress
  readme.md
  picture.png

And in readme.md:

![picture](./picture.png)

And the dist folder will be like this:

dist
  index.html
  picture.png

Am I right?

timaschew commented 5 years ago

Oh, thanks for the examples, I should have provided them ;)

Am I right?

Yes, exactly!

rreinhardt commented 5 years ago

I also would love to see this functionality in place but I think it would be more expansive without the prerequisite that the resource be referenced via an image tag. The case I'd like to have addressed:

file structure:

docs/
  .vuepress
  readme.md
  audio-instructions/
    readme.md
    instructions.m4a
    additional/
       additional1.m4a
       additional2.m4a

and in docs/audio-instructions/readme.md

---
title: this is audio instructions of how to do xyzzy
---

main info
<audio src="./instructions.m4a">

other info
<audio src="./additional/additional1.m4a">
<audio src="./additional/additional2.m4a">

so that dist looks like:

dist/
  index.html
  audio-instructions/
    index.html
    instructions.m4a
    additional/
       additional1.m4a
       additional2.m4a
timaschew commented 5 years ago

Yes, that should work as well, so basically all kind of relative URLs to resources (images, audio, video, etc.)

BTW: @rreinhardt you have two typos: instuctions

shigma commented 5 years ago

@timaschew @rreinhardt I have drafted a PR for this.

1494

PeppeL-G commented 5 years ago

This feature has still not been added to VuePress? @Shigma Maybe you should release the plugin as an npm package so we can start using it?

PeppeL-G commented 4 years ago

I'm not trying to be ungrateful (I can't complain about free stuff), but I've waited for this way too long now and can't wait anymore. Instead, I've come up with my own solution, which simply looks for all files in the src folder (recursively) that does not have the file extension .md and copies them to the same place in the src/.vuepress/public folder when the development server starts (e.g. src/sub-folder/hello.txt is copied to src/.vuepress/public/sub-folder/hello.txt).

Here's the function that does it (add it too src/.vuepress/config.js and call it there):

const fs = require('fs')
const path = require('path')

function copyStaticFilesToPublic(){

    const doNotCopyFilenames = [
        new RegExp("^.*\\.md$"),
    ]

    const doNotCopyFolderNames = [
        new RegExp("^\\.vuepress$")
    ]

    const pathToPublicFolder = path.resolve(__dirname, "public")
    const pathToSrcFolder = path.resolve(__dirname, "../")

    if(fs.existsSync(pathToPublicFolder)){
        fs.rmdirSync(pathToPublicFolder, {recursive: true}) // Requires latest version of node.
    }

    copyAllStaticFiles(pathToSrcFolder, pathToPublicFolder)

    function copyAllStaticFiles(pathToSourceFolder, pathToDestinationFolder){

        if(!fs.existsSync(pathToDestinationFolder)){
            fs.mkdirSync(pathToDestinationFolder)
        }

        const names = fs.readdirSync(
            pathToSourceFolder
        )

        for(const name of names){

            const pathToSource = path.resolve(
                pathToSourceFolder,
                name
            )
            const pathToDestination = path.resolve(
                pathToDestinationFolder,
                name
            )

            if(fs.lstatSync(pathToSource).isDirectory()){

                if(!doNotCopyFolderNames.some(regexp => regexp.test(name))){

                    copyAllStaticFiles(pathToSource, pathToDestination)

                }

            }else{

                if(!doNotCopyFilenames.some(regexp => regexp.test(name))){

                    fs.copyFileSync(pathToSource, pathToDestination)

                }

            }

        }

    }

}

This works great for me, so I share this piece of code if anyone else is in the same situation as me and in need of a quick fix. Remember that the files are only copied when the development server starts, so adding/changing static files after that requires a restart.

akauppi commented 4 years ago

I am a newcomer to VuePress and got my first site published today. https://akauppi.github.io/Kotka/

Found it weird at build steps that so many assets seem to get renamed and pushes to git take time. It looks like this proposal would make the product work the way I intuitively expected it to, which is to pick any pictures relative to markdown files, and pass them on.

Not using public folder and not planning to - I need to see the pictures when editing the markdowns.