Mustom

Simple design theme for VuePress,Blog,耀 の 个人网站 | Mark の Personal Website (QQ Group: 595614161)

Build GitHub package.json version (branch) License

preview

Language:

If you still feel confused after reading this documentation, please read and learn how my $docs is structured here, or welcome to ask me questions via Github Issues.

Any Bug reports or suggestions can be posted into Github Issues in any format.

# Installation

Create a folder with structure as below, and for detailed source folder structure $docs, see $docs. _posts folder refers to $docs/_posts.

# inside the new folder of your site

+ $docs # folder contains source of your site
  - _posts # folder contains posts
  - .vuepress # folder contains static source and config
    + public # folder contains static source
    + config.js # file stores configuration
+ package.json # file generated by using `npm init`

Run one of the following commands in the new folder of your site to install vuepress and vuepress-theme-mustom.

yarn add vuepress-theme-mustom -D

or with npm

npm i vuepress-theme-mustom -D

or manually download the clone .zip file here, and extract the theme source code to the new folder of your site. Then, set theme attribute of config.js as below.

theme: require.resolve('../../vuepress-theme-mustom-master/')

After installation succeeded, your site should be run on localhost using the command below.

vuepress dev \$docs

or built into $docs/.vuepress/dist

vuepress build \$docs

Note: The backward slash ("\") above is an escape character here while typing commands in command line or terminal.

# Explanation of _secret.tpl.js

To see how my _secret.tpl.js looks like, click here.

Using a secret config file, any appid and appkey can be stored locally and referred to config.js as showed below.

const secret = require('./_secret');

module.exports = { // https://www.vuepress.cn/zh/config/
  // ...
  themeConfig: {
    // ...
    translate: secret.translate, // baidu translation
    comment: secret.comment, // vssue setting
    // ...
  }
  // ...
}

# Explanation of config.js

To see how my config.js looks like, click here.

# General VuePress Settings

module.exports = { // https://www.vuepress.cn/zh/config/
  // Entry of used theme
  // theme: require.resolve('../../'), // My value
  // theme: require.resolve('../../vuepress-theme-mustom-master/'), // manually download theme
  theme: 'vuepress-theme-mustom', // Your value
  // Site base
  // base: '/', // My value, due to https://ma-jinyao.cn/
  base: '/MyBlog/', // Your value, if https://yourUsername.github.io/MyBlog/
  // Default title that appended to your site title
  // title: '耀 の 个人网站 | Mark の Personal Website', // My value
  title: 'XXX 的博客 | XXX\'s Blog', // Your value
  // Default description that appended to your site description
  description: 'XXX 的博客, XXX\'s Blog, XXX, Mustom, VuePress',

  themeConfig: {
    // ...
    // About this section, go to header "Configuration of themeConfig"
  }

  // It isn't necessary to change 'head' if you want to replace files directly
  // favicon is in folder $docs/.vuepress/public/
  // apple-touch-icon is in folder $docs/.vuepress/public/assets/img/
  head: [
    // PWA settings, https://www.vuepress.cn/plugin/official/plugin-pwa.html
    ['link', { rel: 'icon', href: '/favicon.ico', type: "image/x-icon" }],
    ['link', { rel: 'manifest', href: '/manifest.json' }],
    ['meta', { name: 'theme-color', content: '#ffffff' }],
    ['meta', { name: 'apple-mobile-web-app-capable', content: 'yes' }],
    ['meta', { name: 'apple-mobile-web-app-status-bar-style', content: '#ffffff' }],
    ['link', { rel: 'apple-touch-icon', href: '/assets/img/apple-touch-icon.png' }]
  ],
  // It isn't necessary to change 'markdown' if you don't mind to use settings below
  // https://www.vuepress.cn/zh/config/#markdown
  markdown: {
    lineNumbers: false,
    extractHeaders: ['h1', 'h2', 'h3', 'h4', 'h5', 'h6']
  },
  // It isn't necessary to change 'evergreen'
  evergreen: true, // using old browser ?
  // To use jsdelivr cdn, you should change the publicPath below
  configureWebpack: () => {
    if (process.env.NODE_ENV === 'production') {
      return {
        output: {
          // My value, username=jinyaoMa, repo=vuepress-theme-mustom, branch=gh-pages
          //publicPath: 'https://cdn.jsdelivr.net/gh/jinyaoMa/vuepress-theme-mustom@gh-pages/'
          // Your value, if username=XXX, repo=MyBlog, branch=gh-pages
          publicPath: 'https://cdn.jsdelivr.net/gh/XXX/MyBlog@gh-pages/'
        }
      }
    }
  }
}

# Configuration of themeConfig

All of following attributes are inside themeConfig of config.js

author, year, maximizeLaunch, noEmpty and images; These attributes are very simple, and you can try yourselves. maximizeLaunch set to true can help you to fully fill the launch with image covering the window. noEmpty can disable the empty component that occupies the empty space. images can let you replace images in custom urls, but you need to follow the structure below.

images: { // for image replacment; no base needed; first layer key points to component name
  ad: '/assets/img/ad.png',
  avatar: '/assets/img/avatar.png',
  brand: '/assets/img/brand.png',
  hitokoto: {
    left: '/assets/img/hitokoto.left.png',
    right: '/assets/img/hitokoto.right.png',
  },
  empty: '/assets/img/empty.png',
  records: '/assets/img/records.png',
},

# domain

This attribute is for sitemap generation ONLY.

  • My value: 'https://ma-jinyao.cn'
  • Your Value: 'https://yourdomain.com/'

# clustrmaps

clustrmaps

Set clustrmaps to null or ignore it to disable above. This requires service from clustrmaps.com.

clustrmaps: {
  id: "clustrmaps", // clstr_globe / clustrmaps
  src: "//cdn.clustrmaps.com/map_v2.js?cl=333333&w=a&t=t&d=kuCCiVvtASTqmAMxPSTLcjxs-p8j6ht3LUi9z9Q-OKc&co=ffffff&cmo=3acc3a&cmn=ff5353&ct=333333"
},

# customBackgrounds

This attribute is for adding background images to the site under skin-default. If there are multiple images, they will be in slide show. You can have value looking like the below.

customBackgrounds: [
  '/assets/img/background.png',
  'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1596065328389&di=ad7a9cc49e45547721005bd528325f0d&imgtype=0&src=http%3A%2F%2Fpic1.win4000.com%2Fwallpaper%2F2%2F58b4ef69ed377.jpg',
  'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1596063652971&di=8b659ee5cd46f4006d082b626eb3bd0d&imgtype=0&src=http%3A%2F%2Fpicture.ik123.com%2Fuploads%2Fallimg%2F180330%2F4-1P330160644.jpg'
],

# socialShare

socialShare

Looking to this for reference. The following example generates the result of above.

socialShare: { // https://sns.goyfe.com/guide/
  networks: ['qq', 'weibo', 'douban', 'email', 'whatsapp', 'facebook', 'reddit', 'telegram', 'line'],
  email: 'jinyao.ma@outlook.com',
  fallbackImage: '/assets/img/avatar.png',
  noGlobalSocialShare: true
},

# notification

notification

msg strings should be in current sequence/index. 0 => zh, 1 => en

You can have multiple notification on start up, and they will be displayed in sequence and one-by-one. msg contains both strings in zh and en. The following example generates the result of above.

notification: [
  { // welcome msg
    type: 'default', // default or warning or error
    msg: [
      '<strong>欢迎来到我的个人网站!技术交流请加 QQ 群:595614161,也可以加本人QQ:907881445,或者点击页面左下角扫码找我哦~<strong>', // zh
      '<strong>Welcome to my personal website! <strong>' // en
    ]
  },
],

# qrcodes

qrcodes

locale strings should be in current sequence/index. 0 => zh, 1 => en

locale contains both string in zh and en. The following example generates the result of above.

qrcodes: [{ // qrcode for contact and friending
  locale: [
    'QQ', // zh
    'QQ' // en
  ],
  path: '/assets/img/qq.png' // no base needed
}, {
  locale: [
    '微信', // zh
    'WeChat' // en
  ],
  path: '/assets/img/wechat.png' // no base needed
}],

header

sitename strings should be in current sequence/index. 0 => zh, 1 => en

sitename contains both string in zh and en. The following example generates the result of above.

header: {
  sitename: [
    '耀 の 个人网站', // zh
    'Mark の Personal Website' // en
  ]
},

# brand

brand

signatures strings should be in current sequence/index. 0 => zh, 1 => en

signatures contains both string in zh and en. The following example generates the result of above.

brand: {
  signatures: [
    '我只想安静地做笔记', // zh
    'I just wanna note silently' // en
  ],
  contacts: [{
    icon: '<i class="fab fa-github fa-fw"></i>',
    text: 'jinyaoMa',
    link: 'https://github.com/jinyaoMa'
  }, {
    icon: '<i class="fas fa-envelope fa-fw"></i>',
    text: 'jinyao.ma@outlook.com',
    link: 'mailto://jinyao.ma@outlook.com'
  }, {
    icon: '<i class="fab fa-qq fa-fw"></i>',
    text: '907881445',
    link: 'tencent://Message/?uin=907881445'
  }]
},

caption and text strings should be in current sequence/index. 0 => zh, 1 => en

caption and text contain both string in zh and en.

You can erase some of the items. This attribute isn't necessary to be edited if you have the same structure as my $docs.

# inside the new folder of your site

+ $docs # folder contains source of your site
  - _posts # folder contains posts, 'Home' and 'Archive' pages are auto-generated
  - .vuepress # folder contains static source and config
  - about # 'About' page
  - codes # 'Code Library' page
  - icons # 'Icon Font Library' page
  - letter # 'Cover Letter Tips' page
  - records # 'Records' page
  - resume # 'Resume Tips' page
  # 'Gallery' page is auto-generated

The following example matches the structure of above.

menus: [{
  caption: [
    '本站', // zh
    'MAIN' // en
  ],
  icon: '<i class="fas fa-sitemap fa-fw"></i>',
  items: [{
    icon: '<i class="fas fa-home fa-fw"></i>',
    text: [
      '首页', // zh
      'Home' // en
    ],
    link: '/'
  }, {
    icon: '<i class="fas fa-archive fa-fw"></i>',
    text: [
      '归档', // zh
      'Archive' // en
    ],
    link: '/archive/'
  }, {
    icon: '<i class="fas fa-user fa-fw"></i>',
    text: [
      '关于', // zh
      'About' // en
    ],
    link: '/about/'
  }]
}, {
  caption: [
    '工作', // zh
    'JOB RELATED' // en
  ],
  icon: '<i class="fas fa-briefcase fa-fw"></i>',
  items: [{
    icon: '<i class="fas fa-paper-plane fa-fw"></i>',
    text: [
      '简历小贴士', // zh
      'Resume Tips' // en
    ],
    link: '/resume/'
  }, {
    icon: '<i class="fas fa-file-contract fa-fw"></i>',
    text: [
      '求职信小贴士', // zh
      'Cover Letter Tips' // en
    ],
    link: '/letter/'
  }]
}, {
  caption: [
    '其他', // zh
    'OTHERS' // en
  ],
  icon: '<i class="fas fa-ellipsis-h fa-fw"></i>',
  items: [{
    icon: '<i class="fas fa-box fa-fw"></i>',
    text: [
      '代码库', // zh
      'Code Library' // en
    ],
    link: '/codes/'
  }, {
    icon: '<i class="fas fa-icons fa-fw"></i>',
    text: [
      '图标字体库', // zh
      'Icon Font Library' // en
    ],
    link: '/icons/'
  }, {
    icon: '<i class="fas fa-edit fa-fw"></i>',
    text: [
      '记录', // zh
      'Records' // en
    ],
    link: '/records/'
  }, {
    icon: '<i class="fas fa-images fa-fw"></i>',
    text: [
      '图库', // zh
      'Gallery' // en
    ],
    link: '/gallery/'
  }]
}],

# meting

meting

The following example generates the result of above.

meting: {
  server: 'netease', // netease, tencent, kugou, xiami, baidu
  type: 'playlist', // song, playlist, album, search, artist
  id: '4989572738', // song id / playlist id / album id / search keyword
  theme: 'var(--link)', // e.g. #ff3300
  height: '297px' // playlist height, 297px ==> 9 lines
},

# portals

portals

The following example generates the result of above.

// external links; use for the component that displays after clicking on the left-top button of header
portals: [{
  name: 'My Site',
  desc: '耀 の 个人网站 | Mark の Personal Website',
  icon: 'https://jinyaoMa.github.io/asset/img/author.medium.png',
  link: 'https://jinyaoMa.github.io/'
}, {
  name: 'MPlayer',
  desc: 'APlayer 个人模仿练习版',
  icon: 'https://blog.ma-jinyao.cn/asset/img/icon.medium.png',
  link: 'https://blog.ma-jinyao.cn/MPlayer'
}, {
  name: 'Resume',
  desc: 'Resume Template',
  icon: 'https://blog.ma-jinyao.cn/extension/resume/icon.png',
  link: 'https://blog.ma-jinyao.cn/extension/resume/english/'
}, {
  name: '简历',
  desc: '简历模板',
  icon: 'https://blog.ma-jinyao.cn/extension/resume/icon.reverse.png',
  link: 'https://blog.ma-jinyao.cn/extension/resume/chinese/'
}, {
  name: 'Cover Letter',
  desc: 'Cover Letter Template',
  icon: 'https://blog.ma-jinyao.cn/extension/letter/icon.png',
  link: 'https://blog.ma-jinyao.cn/extension/letter/english/'
}, {
  name: '求职信',
  desc: '求职信模板',
  icon: 'https://blog.ma-jinyao.cn/extension/letter/icon.reverse.png',
  link: 'https://blog.ma-jinyao.cn/extension/letter/chinese/'
}, {
  name: 'Palette',
  desc: '想知道图片主题色?',
  icon: 'https://blog.ma-jinyao.cn/extension/palette/icon.png',
  link: 'https://blog.ma-jinyao.cn/extension/palette/'
}],

# hitokoto

You can put your words to customs for displaying, and these words are randomly picked on home page loaded. type is for hitokoto service setting referred to developer.hitokoto.cn

hitokoto: {
  customs: [/*{ // format; if customs exist, API will be ignored, and customs will be in use
    word: 'https://developer.hitokoto.cn',
    from: '一言开发者中心'
  }*/],
  type: 'i' // https://developer.hitokoto.cn/sentence/#请求参数
},

You can add online images to gallery page, and they will be inserted to very top of the page and following by your local images that are auto appended. Local images are located at /$docs/.vuepress/public/gallery. To see mine, click here.

gallery: [/*{ format; these gallery items will be appended to /gallery/ page
  name: 'test image from baidu',
  url: 'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1596063652971&di=8b659ee5cd46f4006d082b626eb3bd0d&imgtype=0&src=http%3A%2F%2Fpicture.ik123.com%2Fuploads%2Fallimg%2F180330%2F4-1P330160644.jpg'
}*/],

# pwa

message and buttonText strings should be in current sequence/index. 0 => zh, 1 => en

message and buttonText contain both string in zh and en.

popupComponent is set to the custom component in theme source code. If you don't like the update popup, you can set updatePopup to false. Or if you don't want to use service worker, you can set both serviceWorker and updatePopup to false.

pwa: { // https://www.vuepress.cn/plugin/official/plugin-pwa.html
  serviceWorker: true,
  popupComponent: 'CustomSWUpdatePopup',
  updatePopup: {
    message: [
      '检测到可用的新内容。', // zh
      'New content is available.' // en
    ],
    buttonText: [
      '更新缓存', // zh
      'Refresh' // en
    ]
  }
}

# Front-Matter for Posts

categories and tags should be in flat. This theme does NOT support multi-dimensional arrays.

Every post should have similar structure of front-matter as showed below.

---
title: 'Post Title'
categories: # flat, ONLY ONE layer acceptable
  - cate1
  - cate2
tags: # flat, ONLY ONE layer acceptable
  - tag1
  - tag2
date: 2020-12-12 00:00:00
updated: 2020-12-12 00:00:00
---

# Front-Matter for Normal Pages

Example from my 'About' page, or to look at the original index.md file, click here.

---
title: 关于 | About
---

# Want to have a page similar to my 'Records' page?

Follow the format as showed below, or to look at the original index.md file of my 'Records' page, click here.

---
title: # page title
records:
  enabled: true # set this to true to enable Records component
  items:
    - cover: # [empty] to use default cover
      date: # string
      title:
      # e.g. [empty]
      # e.g. book / article / paper / newspaper / report / picture / anime / video / movie / audio / project / website
      # e.g. [customized] --> "Journal"
      type:
      author:
      source:
      # format 'number/total' OR '100%' OR [customized]; [empty] to use 'N/A', NO DECIMAL POINT ALLOW
      # e.g. 12 / 34 ; 32/52 ; 22% ; 88% ; "Latest" ; "Complete"
      progress:
      summary:
---

# Want to have a page similar to my 'Code Library' page?

To see how the Code Library structured in a Github Repository, refer to jinyaoMa/code-lib

Follow the format as showed below, or to look at the original index.md file of my 'Code Library' page, click here.

---
title: # page title
github:
  user: # Github username
  repo: # Github repo
  readme:
    enabled: true # set this to true to enable Readme component
  stack:
    enabled: true # set this to true to enable Stack component
---

# Want to have a page similar to my 'Icon Font Library' page?

To see how the Icon Font Library structured in a Github Repository, refer to jinyaoMa/icon-lib

Follow the format as showed below, or to look at the original index.md file of my 'Icon Font Library' page, click here.

---
title: # page title
github:
  user: # Github username
  repo: # Github repo
  readme:
    enabled: true # set this to true to enable Readme component
  iframe:
    enabled: true # set this to true to enable Iframe component
    url: https://blog.ma-jinyao.cn/icon-lib/ # subpage should be in same-origin
---

Made with ❤️ by Ahmad Mostafa - @z3by