Vuepress: 关于文档分类、归档的问题

Created on 24 May 2018  ·  10Comments  ·  Source: vuejs/vuepress


Feature request



What problem does this feature solve?

很多静态网站生成工具,例如Hexo、Jekyll都支持文章分类、标签及归档,目前VuePress必须手动维护配置文件,需要在 themeConfig.locales.sidebar 中手动添加侧边栏目录,希望之后的版本以一种自动添加指定 .md 文件 的 frontmatter 为目录的方式。

What does the proposed API look like?

How should this be implemented in your opinion?

可以通过 frontmatter 添加 category 和 tags 的方式创建分类,通过相同的 category 和 tags 创建分类目录,可以在Vue的原型中添加 $category 和 $tags 的钩子,比如有一个叫 'frontend' 的分类,可以使用 $category['frontmatter'] 来访问。

Are you willing to work on this yourself?**

暂时没打算自己做,对 VuePress 源码还没研究透彻 !

feature request next

Most helpful comment

Solution

util.js

// 生成分类
function generateCates (pages) {
  let allSingleArticles = []
  let recommandArticles = []
  let favorites = [
    { index: 1, title: '插件收藏', pages: [] },
    { index: 2, title: '网址收藏', pages: [] },
    { index: 3, title: '实用工具', pages: [] }
  ]
  let cates = {}
  // 遍历所有文章
  pages.forEach(page => {
    let frontmatter = page.frontmatter
    // 所有单页文章
    if (frontmatter.title && frontmatter.datetime && !(frontmatter.allList === false)) {
      allSingleArticles.push(page)
      if (frontmatter.recommand) {
        // 所有推荐文章
        recommandArticles.push(page)
      }
    }
    // 收藏夹
    if (frontmatter.favoriteType) {
      let index = page.frontmatter.favoriteType
      if (index === favorites[index - 1].index) {
        favorites[index - 1].pages.push(page)
      }
    }
    // 分类
    if (frontmatter.category) {
      // 分类
      if (frontmatter.category instanceof Array) {
        // 分类是一个数组
        let categories = frontmatter.category
        categories.forEach(cate => {
          if (!cates[cate]) {
            // 分类不存在
            cates[cate] = []
            cates[cate].push(page)
          } else {
            // 分类已存在
            cates[cate].push(page)
          }
        })
      } else {
        // 分类为单一类别
        let cate = page.frontmatter.category
        if (!cates[cate]) {
          // 分类不存在
          cates[cate] = []
          cates[cate].push(page)
        } else {
          // 分类已存在
          cates[cate].push(page)
        }
      }
    }
  })
  // 排序
  allSingleArticles = allSingleArticles.sort((a, b) => {
    return new Date(b.frontmatter.datetime) - new Date(a.frontmatter.datetime)
  })
  recommandArticles = recommandArticles.sort((a, b) => {
    return new Date(b.frontmatter.datetime) - new Date(a.frontmatter.datetime)
  })
  favorites.forEach((favorite, index) => {
    favorites[index] = {
      index: favorite.index,
      title: favorite.title,
      pages: favorite.pages.sort((a, b) => {
        return new Date(a.frontmatter.datetime) - new Date(b.frontmatter.datetime)
      })
    }
  })
  for (let cate in cates) {
    cates[cate] = cates[cate].sort((a, b) => {
      return new Date(b.frontmatter.datetime) - new Date(a.frontmatter.datetime)
    })
  }
  return {
    allSingleArticles, recommandArticles, favorites, cates
  }
}

export default {
  generateCates
}

enhanceApp.js

import util from './util'

export default ({
  Vue, // VuePress 正在使用的 Vue 构造函数
  options, // 附加到根实例的一些选项
  router, // 当前应用的路由实例
  siteData // 站点元数据
}) => {
  // 添加分类
  let categories = util.generateCates(siteData.pages)
  siteData.themeConfig.categories = categories.cates
  siteData.themeConfig.favorites = categories.favorites
  siteData.themeConfig.allSingleArticles = categories.allSingleArticles
  siteData.themeConfig.recommandArticles = categories.recommandArticles
}

usage:

this.$site.themeConfig.categories
this.$site.themeConfig.favorites

console:

wx20180901-051901

see: https://www.xiaoyulive.top

All 10 comments

Thanks,

I'll appreciate if you take the time to translate the issue to English so anybody can answer, you will also benefit from this :)

solution

I wrote down the following methods to implement classification

function generateCates () {
  let cates = {}
  this.$site.pages.forEach(category => {
    if (category.frontmatter.category) {
      let cate = category.frontmatter.category
      if (!cates[cate]) {
        cates[cate] = []
        cates[cate].push(category)
      } else {
        cates[cate].push(category)
      }
    }
  })
  return cates
}

see https://github.com/quanzaiyu/xiaoyulive-vuepress/blob/master/website/.vuepress/theme/util.js (line 243)

Vue.prototype['$categories'] = this.generateCates()

see https://github.com/quanzaiyu/xiaoyulive-vuepress/blob/master/website/.vuepress/theme/Layout.vue (line 102)

usage

Vue

this.$categories['xxx']

see https://github.com/quanzaiyu/xiaoyulive-vuepress/blob/master/website/.vuepress/theme/layouts/List.vue (line 35)

Markdown: add frontmatter

---
category: JavaScript
---

I need this too. I want to build a blog theme with classification, tags, and archives included. But I want it supported by official developers of vuepress so that it may benefit more developers.

Vuepress is originally designed for documents, in which cases categories/tags are not necessary.

As more people being interested in Vuepress, blog support (like categories, tags, etc.) has been requested for months.

@ulivz is working on plugin system to make Vuepress more customizable, and will be released in v1.0.0. After that, blog/theme/anything-you-want could be realized via plugins. You can take a look at the next branch for the progress of that.

So in version 0.x, you may have to add some code to support this feature as @quanzaiyu did. FYI, I also make a simple workaround via enhanceApp.js in my blog theme.

I think what you want is this theme

@Bloss I've added your theme here. Hope you don't mind 😄

@meteorlxy Amazing

Solution

util.js

// 生成分类
function generateCates (pages) {
  let allSingleArticles = []
  let recommandArticles = []
  let favorites = [
    { index: 1, title: '插件收藏', pages: [] },
    { index: 2, title: '网址收藏', pages: [] },
    { index: 3, title: '实用工具', pages: [] }
  ]
  let cates = {}
  // 遍历所有文章
  pages.forEach(page => {
    let frontmatter = page.frontmatter
    // 所有单页文章
    if (frontmatter.title && frontmatter.datetime && !(frontmatter.allList === false)) {
      allSingleArticles.push(page)
      if (frontmatter.recommand) {
        // 所有推荐文章
        recommandArticles.push(page)
      }
    }
    // 收藏夹
    if (frontmatter.favoriteType) {
      let index = page.frontmatter.favoriteType
      if (index === favorites[index - 1].index) {
        favorites[index - 1].pages.push(page)
      }
    }
    // 分类
    if (frontmatter.category) {
      // 分类
      if (frontmatter.category instanceof Array) {
        // 分类是一个数组
        let categories = frontmatter.category
        categories.forEach(cate => {
          if (!cates[cate]) {
            // 分类不存在
            cates[cate] = []
            cates[cate].push(page)
          } else {
            // 分类已存在
            cates[cate].push(page)
          }
        })
      } else {
        // 分类为单一类别
        let cate = page.frontmatter.category
        if (!cates[cate]) {
          // 分类不存在
          cates[cate] = []
          cates[cate].push(page)
        } else {
          // 分类已存在
          cates[cate].push(page)
        }
      }
    }
  })
  // 排序
  allSingleArticles = allSingleArticles.sort((a, b) => {
    return new Date(b.frontmatter.datetime) - new Date(a.frontmatter.datetime)
  })
  recommandArticles = recommandArticles.sort((a, b) => {
    return new Date(b.frontmatter.datetime) - new Date(a.frontmatter.datetime)
  })
  favorites.forEach((favorite, index) => {
    favorites[index] = {
      index: favorite.index,
      title: favorite.title,
      pages: favorite.pages.sort((a, b) => {
        return new Date(a.frontmatter.datetime) - new Date(b.frontmatter.datetime)
      })
    }
  })
  for (let cate in cates) {
    cates[cate] = cates[cate].sort((a, b) => {
      return new Date(b.frontmatter.datetime) - new Date(a.frontmatter.datetime)
    })
  }
  return {
    allSingleArticles, recommandArticles, favorites, cates
  }
}

export default {
  generateCates
}

enhanceApp.js

import util from './util'

export default ({
  Vue, // VuePress 正在使用的 Vue 构造函数
  options, // 附加到根实例的一些选项
  router, // 当前应用的路由实例
  siteData // 站点元数据
}) => {
  // 添加分类
  let categories = util.generateCates(siteData.pages)
  siteData.themeConfig.categories = categories.cates
  siteData.themeConfig.favorites = categories.favorites
  siteData.themeConfig.allSingleArticles = categories.allSingleArticles
  siteData.themeConfig.recommandArticles = categories.recommandArticles
}

usage:

this.$site.themeConfig.categories
this.$site.themeConfig.favorites

console:

wx20180901-051901

see: https://www.xiaoyulive.top

1.x is going to reach beta stage, so you can start to write a plugin for it.

FYI: there has been an official plugin @vuepress/plugin-blog and a demonstration theme.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

sankincn picture sankincn  ·  3Comments

cfjedimaster picture cfjedimaster  ·  3Comments

shaodahong picture shaodahong  ·  3Comments

genedronek picture genedronek  ·  3Comments

ynnelson picture ynnelson  ·  3Comments