Skip to content

Commit

Permalink
chore: 增加 eslint
Browse files Browse the repository at this point in the history
  • Loading branch information
shanyuhai123 committed Dec 14, 2020
1 parent 1a7c784 commit 195e7f9
Show file tree
Hide file tree
Showing 6 changed files with 156 additions and 126 deletions.
15 changes: 15 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
module.exports = {
env: {
browser: true,
commonjs: true,
es2021: true,
node: true,
jest: true
},
extends: [
'standard'
],
parserOptions: {
ecmaVersion: 12
}
}
66 changes: 33 additions & 33 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,70 +1,70 @@
const fs = require('fs');
const path = require('path');
const fs = require('fs')
const path = require('path')
const colors = require('colors/safe')

const colors = require("colors/safe");
const { getMenuPath, getFilename, filterRootMarkdowns, groupBy, genSidebar, titleSort, sidebarSort, findGroupIndex, genNav } = require("./lib/utils");
const sidebarOptions = require("./lib/options");
const { getMenuPath, getFilename, filterRootMarkdowns, groupBy, genSidebar, titleSort, sidebarSort, findGroupIndex, genNav } = require('./lib/utils')
const sidebarOptions = require('./lib/options')

let SIDEBAR = Object.create(null);
let SIDEBAR = Object.create(null)

module.exports = (options, ctx) => ({
name: "vuepress-plugin-auto-sidebar",
async ready() {
name: 'vuepress-plugin-auto-sidebar',
async ready () {
try {
const mergeOptions = Object.assign({}, sidebarOptions, options);
const { pages } = ctx;
const mergeOptions = Object.assign({}, sidebarOptions, options)
const { pages } = ctx

// 整理 pages 数据
const mapPages = pages.filter(page => page.relativePath).map(page => ({
frontmatter: page.frontmatter,
menuPath: getMenuPath(page.relativePath),
filename: getFilename(page.relativePath)
})).filter(filterRootMarkdowns);
})).filter(filterRootMarkdowns)

// 过滤出待排序的
const sortQueue = mapPages.filter(page => page.frontmatter.autoPrev || page.frontmatter.autoNext);
const defaultPages = mapPages.filter(page => !page.frontmatter.autoPrev && !page.frontmatter.autoNext);
const sortQueue = mapPages.filter(page => page.frontmatter.autoPrev || page.frontmatter.autoNext)
const defaultPages = mapPages.filter(page => !page.frontmatter.autoPrev && !page.frontmatter.autoNext)

const groupByDepth = groupBy(defaultPages, "menuPath");
const groupByDepth = groupBy(defaultPages, 'menuPath')

titleSort(groupByDepth, mergeOptions.sort);
let sortQueueCache = [];
titleSort(groupByDepth, mergeOptions.sort)
let sortQueueCache = []
while (sortQueue.length) {
const current = sortQueue.pop();
const index = findGroupIndex(current, groupByDepth);
const current = sortQueue.pop()
const index = findGroupIndex(current, groupByDepth)

if (index !== -1) {
current.frontmatter.autoPrev ?
groupByDepth[current.menuPath].splice(index + 1, 0, current) :
groupByDepth[current.menuPath].splice(index, 0, current)
current.frontmatter.autoPrev
? groupByDepth[current.menuPath].splice(index + 1, 0, current)
: groupByDepth[current.menuPath].splice(index, 0, current)

sortQueue.push(...sortQueueCache);
sortQueueCache = [];
sortQueue.push(...sortQueueCache)
sortQueueCache = []
} else {
sortQueueCache.push(current);
sortQueueCache.push(current)
}
}

if (sortQueueCache.length) {
console.log(colors.red("\nvuepress plugin auto sidebar(精准排序): "), `\n [${colors.green(sortQueueCache.map(q => `${q.filename}(${q.frontmatter.title})`).join("、"))}] \t共 ${sortQueueCache.length} 个文件指向了不存在的 prev 或 next`);
console.log(colors.red('\nvuepress plugin auto sidebar(精准排序): '), `\n [${colors.green(sortQueueCache.map(q => `${q.filename}(${q.frontmatter.title})`).join('、'))}] \t共 ${sortQueueCache.length} 个文件指向了不存在的 prev 或 next`)
}

SIDEBAR = genSidebar(sidebarSort(groupByDepth), mergeOptions);
SIDEBAR = genSidebar(sidebarSort(groupByDepth), mergeOptions)

const nav = genNav(SIDEBAR);
const dest = path.join(ctx.sourceDir, ".vuepress/nav.js");
const nav = genNav(SIDEBAR)
const dest = path.join(ctx.sourceDir, '.vuepress/nav.js')

if (mergeOptions.nav && !fs.existsSync(dest)) {
await fs.writeFileSync(dest, `module.exports = ${JSON.stringify(nav)};`);
await fs.writeFileSync(dest, `module.exports = ${JSON.stringify(nav)};`)
}
} catch (ex) {
console.error(ex);
console.error(ex)
}
},
async enhanceAppFiles() {
async enhanceAppFiles () {
return {
name: "auto-sidebar-enhance",
name: 'auto-sidebar-enhance',
content: `export default ({ siteData, options }) => { siteData.themeConfig.sidebar = ${JSON.stringify(SIDEBAR)} }`
}
}
});
})
8 changes: 4 additions & 4 deletions lib/options.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
module.exports = {
sort: "asc", // 排序
titleMode: "default", // 标题模式
sort: 'asc', // 排序
titleMode: 'default', // 标题模式
titleMap: {}, // 标题映射
nav: false, // 导航栏
sidebarDepth: 1, // 标题深度
collapsable: false, // 折叠
collapseList: [], // 折叠列表
uncollapseList: [], // 不折叠列表
}
uncollapseList: [] // 不折叠列表
}
153 changes: 81 additions & 72 deletions lib/utils.js
Original file line number Diff line number Diff line change
@@ -1,142 +1,151 @@
// base 基础
const getMenuPath = path => padMenuPath(path.split("/").slice(0, -1).join("/"));
const getFilename = path => path.split("/").slice(-1).toString().replace(".md", "");
const padMenuPath = path => `${path.startsWith("/") ? "" : "/"}${path}${path.endsWith("/") ? "" : "/"}`;
const getMenuPath = path => padMenuPath(path.split('/').slice(0, -1).join('/'))
const getFilename = path => path.split('/').slice(-1).toString().replace('.md', '')
const padMenuPath = path => `${path.startsWith('/') ? '' : '/'}${path}${path.endsWith('/') ? '' : '/'}`

const filterRootMarkdowns = page => page.menuPath !== "//";
const filterRootMarkdowns = page => page.menuPath !== '//'

const groupBy = (arr, fn) =>
arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val, i) => {
acc[val] = (acc[val] || []).concat(arr[i]);
return acc;
}, {});
acc[val] = (acc[val] || []).concat(arr[i])
return acc
}, {})

const genGroup = (title, children = [''], collapsable = false, sidebarDepth = 1) => ({
title,
collapsable,
sidebarDepth,
children
});
})

const genSidebar = (groups, options) => Object.keys(groups).reduce((acc, group) => {
const defaultTitle = formatTitle(group.split("/").slice(-2, -1).toString(), options.titleMode, options.titleMap);
const { above, default: defaultGroup, below } = divideMoreGroups(groups[group]);
above.sort((a, b) => a.sort - b.sort >= 0 ? -1 : 1);
below.sort((a, b) => a.sort - b.sort >= 0 ? 1 : -1);
const defaultTitle = formatTitle(group.split('/').slice(-2, -1).toString(), options.titleMode, options.titleMap)
const { above, default: defaultGroup, below } = divideMoreGroups(groups[group])
above.sort((a, b) => a.sort - b.sort >= 0 ? -1 : 1)
below.sort((a, b) => a.sort - b.sort >= 0 ? 1 : -1)

const collapsable = options.collapseList.find(co => co === group) ? true : options.collapseList.find(co => co === group) ? false : options.collapsable;
const collapsable = options.collapseList.find(co => co === group) ? true : options.collapseList.find(co => co === group) ? false : options.collapsable

acc[group] = [
...above.map(a => genGroup(a.groupName, a.children, collapsable, options.sidebarDepth)),
genGroup(defaultTitle, defaultGroup, collapsable, options.sidebarDepth),
...below.map(a => genGroup(a.groupName, a.children, collapsable, options.sidebarDepth)),
];
...below.map(a => genGroup(a.groupName, a.children, collapsable, options.sidebarDepth))
]

return acc;
return acc
}, {})

// title 相关函数
const toDefaultCase = str => str;
const toLowerCase = str => str.toLowerCase();
const toUpperCase = str => str.toUpperCase();
const toDefaultCase = str => str
const toLowerCase = str => str.toLowerCase()
const toUpperCase = str => str.toUpperCase()
const toCapitalize = ([first, ...rest], lowerRest = false) =>
first.toUpperCase() + (lowerRest ? rest.join('').toLowerCase() : rest.join(''));
first.toUpperCase() + (lowerRest ? rest.join('').toLowerCase() : rest.join(''))
const toCamelCase = str => {
let s =
const s =
str &&
str
.match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g)
.map(x => x.slice(0, 1).toUpperCase() + x.slice(1).toLowerCase())
.join('');
return s.slice(0, 1).toLowerCase() + s.slice(1);
};
.join('')
return s.slice(0, 1).toLowerCase() + s.slice(1)
}
const toKebabCase = str =>
str &&
str
.match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g)
.map(x => x.toLowerCase())
.join('-');
.join('-')
const toTitleCase = str =>
str
.match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g)
.map(x => x.charAt(0).toUpperCase() + x.slice(1))
.join(' ');
.join(' ')

const TITLE_MODE = {
"default": toDefaultCase,
"lowercase": toLowerCase,
"uppercase": toUpperCase,
"capitalize": toCapitalize,
"camelcase": toCamelCase,
"kebabcase": toKebabCase,
"titlecase": toTitleCase,
};
default: toDefaultCase,
lowercase: toLowerCase,
uppercase: toUpperCase,
capitalize: toCapitalize,
camelcase: toCamelCase,
kebabcase: toKebabCase,
titlecase: toTitleCase
}

const formatTitle = (title = "", mode = "default", map = {}) => map[title] || (TITLE_MODE[mode.toLowerCase()] || TITLE_MODE["default"])(title);
const formatTitle = (title = '', mode = 'default', map = {}) => map[title] || (TITLE_MODE[mode.toLowerCase()] || TITLE_MODE.default)(title)

// 排序
const SORT_OPTIONS = {
"asc": (key) => (a, b) => a[key] > b[key] ? 1 : -1,
"desc": (key) => (a, b) => a[key] > b[key] ? -1 : 1
};
asc: (key) => (a, b) => a[key] > b[key] ? 1 : -1,
desc: (key) => (a, b) => a[key] > b[key] ? -1 : 1
}

const titleSort = (obj, mode, key = "filename") => Object.values(obj).forEach(s => {
if (typeof mode === "function") {
return s.sort(mode(key));
const titleSort = (obj, mode, key = 'filename') => Object.values(obj).forEach(s => {
if (typeof mode === 'function') {
return s.sort(mode(key))
}

s.sort((SORT_OPTIONS[mode] || SORT_OPTIONS["asc"])(key))
});
const sidebarSort = sidebar => Object.keys(sidebar).sort((a, b) => a.length > b.length ? -1 : 1).reduce((acc, cur) => (acc[cur] = sidebar[cur], acc), {})
s.sort((SORT_OPTIONS[mode] || SORT_OPTIONS.asc)(key))
})
const sidebarSort = sidebar => Object.keys(sidebar).sort((a, b) => a.length > b.length ? -1 : 1).reduce((acc, cur) => { acc[cur] = sidebar[cur]; return acc }, {})

const findGroupIndex = (cur, obj) => {
const arr = obj[cur.menuPath];
const prev = cur.frontmatter.autoPrev;
const next = cur.frontmatter.autoNext;
if (!arr) return -1;
const arr = obj[cur.menuPath]
const prev = cur.frontmatter.autoPrev
const next = cur.frontmatter.autoNext
if (!arr) return -1

// 当两者均存在时,取 prev
if (prev) {
return arr.findIndex(item => item.filename === prev);
return arr.findIndex(item => item.filename === prev)
} else if (next) {
return arr.findIndex(a => a.filename === next);
return arr.findIndex(a => a.filename === next)
} else {
return -1;
return -1
}
}

// group
const divideReg = /autoGroup([+-])(\d*)/;
const divideReg = /autoGroup([+-])(\d*)/

const divideMoreGroups = arr => arr.reduce((acc = {}, cur) => {
const autoGroup = Object.keys(cur.frontmatter).find(f => divideReg.test(f));
const filename = cur.filename === 'README' ? '' : cur.filename;
const autoGroup = Object.keys(cur.frontmatter).find(f => divideReg.test(f))
const filename = cur.filename === 'README' ? '' : cur.filename

if (!autoGroup) {
acc.default.push(filename);
acc.default.push(filename)
} else {
const autoGroupName = cur.frontmatter[autoGroup];
const [, symbol, sort] = autoGroup.match(divideReg);
const autoGroupName = cur.frontmatter[autoGroup]
const [, symbol, sort] = autoGroup.match(divideReg)

if (symbol === '+') {
const findGroup = acc.above.find(a => a.groupName === autoGroupName)
findGroup ? findGroup.children.push(filename) : acc.above.push({
groupName: autoGroupName,
sort,
children: [filename]
})

if (findGroup) {
findGroup.children.push(filename)
} else {
acc.above.push({
groupName: autoGroupName,
sort,
children: [filename]
})
}
}
if (symbol === '-') {
const findGroup = acc.below.find(a => a.groupName === autoGroupName)
findGroup ? findGroup.children.push(filename) : acc.below.push({
groupName: autoGroupName,
sort,
children: [filename]
})
if (findGroup) {
findGroup.children.push(filename)
} else {
acc.below.push({
groupName: autoGroupName,
sort,
children: [filename]
})
}
}
}

return acc;
return acc
}, {
above: [],
default: [],
Expand All @@ -145,17 +154,17 @@ const divideMoreGroups = arr => arr.reduce((acc = {}, cur) => {

// nav
const genNav = sides => Object.keys(sides).reduce((acc, cur) => {
const [, menu] = cur.split("/");
const [{ title }] = sides[cur];
const re = acc.find(a => a.text === menu);
const [, menu] = cur.split('/')
const [{ title }] = sides[cur]
const re = acc.find(a => a.text === menu)

if (re) {
re.items.push({ text: title, link: cur })
} else {
acc.push({ text: menu, items: [{ text: title, link: cur }] })
}

return acc;
return acc
}, [])

module.exports = {
Expand Down
Loading

0 comments on commit 195e7f9

Please sign in to comment.