ozum / vuepress-bar

VuePress sidebar and navbar generator based on file and directory structure. Focus your documents, not sidebar or navbar.
90 stars 40 forks source link

Sidebar does not work properly with index.js #33

Closed rickalex21 closed 3 years ago

rickalex21 commented 3 years ago

Hey there, thanks for taking the time to write the awesome plugin. I noticed that it does not work with files named AREADME.md, I think this is because of the regex endswith filter in the plugin but that's not a big deal. Maybe try this???

const regex = new RegExp('^readme$','i');

I noticed today when filtering the frontmatter if you set a draft to true it will prevent all the items in the parent directory from showing up. For example:

├── code
│   ├── README.md draft: false
│   └── lua.md draft: true
|   └── python.md draft: false

Nothing will appear under code, python should appear because draft is false.

Here is the code to try in src/.vuepress/theme/index.js

        async ready(){
            ctx.pages.splice(
              0,
              ctx.pages.length,
              ...ctx.pages.filter(({ frontmatter }) => {
                  let title = frontmatter.title
                  let draft = frontmatter.draft
                  console.log('frontmatter.draft is ',draft, title );
                 return  draft !== true
                }),
            )
    },
ozum commented 3 years ago

Could you please open a sample repo showing the problem, so I can test the issue? Also, please describe what is the expected output.

rickalex21 commented 3 years ago

I created a repo here. All the details are explained there. You can comment on there if you want but it's better to comment here because I will be deleting that repo once this gets fixed.

Thanks

ozum commented 3 years ago

@rickalex21 thanks for reporting and creating the repo. Please see some solutions for the problems you reported in the repo.

  1. Setting files frontmatter to draft: true will make all the items in code/ disappear from the sidebar. Expected behavior is to show the draft: false items but not the draft: true.

vuepress-bar is executed before the ready function, so it is impossible to access the custom logic you defined in the ready function.

I try to solve this issue by adding a new filter option, which you can define your custom filter function.

You can use the example below with version 0.4.1

const { nav, sidebar } = getConfig({ filter: (meta) => { meta.draft !== true } });
  1. Adding a file that ends with README.md like AREADME.md will cause an error. This is because the plugin uses endswith string method instead of using a RegExpr?

Fixed

  1. When installing the plugin the home page index.md must be renamed to README.md or you will get this error. I'm not sure if the plugin is accounting for index.md files. In vuepress pages can be named index.md or readme.md.

This is a good request, but currently, it requires lots of my time, so I have to pass this because it could be avoided by using README.md files as you already suggested.

Of course, PR for this is appreciated.

rickalex21 commented 3 years ago

@ozum

const { nav, sidebar } = getConfig({ filter: (meta) => { meta.draft !== true } });

With brackets you have to use return, needs to be udpated to this in the readme.

const { nav, sidebar } = getConfig({ filter: (meta) =>  meta.draft !== true  });

Front Matter mate data is passed as an object.

Also in the readme there was a typo.

Frontmatter meta data is passed as an object.

Another thing is that the filter has to be the same as what is in the ready function or there will be an error because the ready function deletes the pages. This is not a big deal because I don't know that anyone would want to exclude any page other than the frontmatter.draft from a website. I wouldn't do this but if someone did they would have to to match the sidebar filter you added or there will be an error.

//theme/index.js ready function
return  days(30,frontmatter) && draft !== true // If file date was within the last 30 days and draft is false delete the page

How would I go about only showing the root folder with it's children? I'm not to sure how to configure it, it looks similar to the vuepress docs. The way it's setup now is that the entire website is shown in the sidebar. Is this something I would have modify in the components of the theme or something that I can do in the sidebar configuration?

Right now the sidebar shows:

|--CODE
    |--File1.md
    |--File2.md
|--POST
    |--Post1.md
    |--Post2.md

On the nav when I click on POST I only want POST to show because that's the root I don't want the entire website which show's CODE as well. If I could add HOME or UP to the top as well that would be great.

|--HOME
|--POST
    |--Post1.md
    |--Post2.md

Other than that, it looks great. Thanks

ozum commented 3 years ago

Thanks, I fixed typos and added warning for filter function.

You want to have multi sidebar based on current nav option. There is only one way to have this in Vuepress-bar. You should add nav prefix to folder names to use auto nav feature similar to example in README:

|--nav.01.CODE
    |--File1.md
    |--File2.md
|--nav.02.POST
    |--Post1.md
    |--Post2.md

You still can customize generated nav:

const { nav, sidebar } = getConfig(options);
module.exports = { themeConfig: { nav: { ...nav, ...customNav }, sidebar } };
rickalex21 commented 3 years ago

@ozum So basically, If I wanted to achieve that then do it manually without the plugin?

I'm not sure I understand what the benefit of having the prefix is? This here:

    nav: [ 
        {text: 'HOME', link: '/', },
        {text: 'post', link: '/post/'},
        {text: 'code', link: '/code/'},
    ],
    sidebar: {
        '/post/': [ { title: 'Post', children: [ ''] } ],
        '/code/': [ { title: 'Code', children: [ 'misc/','misc/nested/'] } ],
      }

Is pretty much the same as this but I don't have to prefix the folders.

    nav: [ 
        { text: 'HOME', link: '/', },
        {text: 'post', link: '/nav.01.post/'},
        {text: 'code', link: '/nav.02.code/'},
    ],
    sidebar: {
        '/nav.01.post/': [ { title: 'Post', children: [ ''] } ],
        '/nav.02.code/': [ { title: 'Code', children: [ 'misc/','misc/nested/'] } ],
      }

The benefit to having the plugin is that you can have the entire website on the sidebar and no additional code is needed. Along with the other things that you mentioned in the readme.

I know this would be more work but it would be cool if a user could just do show_nested:true or nested: true and it would display all the folders and children instead of manually adding them.

    sidebar: {
        '/post/': [ { title: 'Post', children: [ ''] } ],
        '/code/': [ { title: 'Code', show_nested: true } ],
      }

The way it is right now if I'm not mistaken I would have to do this:

sidebar:{
 '/code/': [ { title: 'Code', children: [
             'misc/','misc/file1', 'misc/file2','misc/file3' .... .... ...
            ] } ],
}

This would be a lot of work if there are multiple folders, files, and nested items as children.

ozum commented 3 years ago

@rickalex21 you don't need any manual code. (If you want you can)

For your example repo, rename files as below.

image

Now, use config below and see everything is created automatically.

const { description } = require('../../package')

const getConfig = require("vuepress-bar");
const path = require('path')
const {nav,sidebar} = getConfig(path.resolve(__dirname,'..'), { filter: (meta) => meta.draft !== true });

console.log(sidebar)

module.exports = {
  /**
   * Ref:https://v1.vuepress.vuejs.org/config/#title
   */
  title: 'Vuepress Docs Boilerplate',
  /**
   * Ref:https://v1.vuepress.vuejs.org/config/#description
   */
  description: description,

  /**
   * Extra tags to be injected to the page HTML `<head>`
   *
   * ref:https://v1.vuepress.vuejs.org/config/#head
   */
  head: [
    ['meta', { name: 'theme-color', content: '#3eaf7c' }],
    ['meta', { name: 'apple-mobile-web-app-capable', content: 'yes' }],
    ['meta', { name: 'apple-mobile-web-app-status-bar-style', content: 'black' }]
  ],

  /**
   * Theme configuration, here is the default theme configuration for VuePress.
   *
   * ref:https://v1.vuepress.vuejs.org/theme/default-theme-config.html
   */
  themeConfig: {
    repo: '',
    editLinks: false,
    docsDir: '',
    editLinkText: '',
    lastUpdated: false,
    sidebarDepth: 6, 
    sidebar,
    nav,
  },

  /**
   * Apply plugins,ref:https://v1.vuepress.vuejs.org/zh/plugin/
   */
  plugins: [
    '@vuepress/plugin-back-to-top',
    '@vuepress/plugin-medium-zoom',
  ]
}
rickalex21 commented 3 years ago

@ozum Thanks that worked 👍 I appreciate your help. The only down side to it is the slug /nav.02.code/, but I'm sure there's probably a way to change that in vuepress to convert /nav.02.code/ to /code/. I'm still fairly new to vue and vuepress.

ozum commented 3 years ago

I'm happy that I can help.