const path = require('path') const setFrontmatter = require('./node_utils/setFrontmatter') const getSidebarData = require('./node_utils/getSidebarData') const { createPage, deletePage } = require('./node_utils/handlePage') const chalk = require('chalk') // 命令行打印美化 const yaml = require('js-yaml') // yaml转js const log = console.log // md容器名 const CARD_LIST = 'cardList' const CARD_IMG_LIST = 'cardImgList' // siteConfig base 配置 let base = '' // Theme API. module.exports = (options, ctx) => { const { sourceDir, themeConfig, siteConfig } = ctx // base路径 base = siteConfig.base || '' // 自动设置front matter setFrontmatter(sourceDir, themeConfig) // 自动生成结构化侧边栏 const sidebar = themeConfig.sidebar if (sidebar === 'structuring' || sidebar && sidebar.mode === 'structuring') { const collapsable = themeConfig.sidebar.collapsable === false ? false : true const sidebarData = getSidebarData(sourceDir, collapsable) if (sidebarData) { themeConfig.sidebar = sidebarData log(chalk.blue('tip ') + chalk.green('add sidebar data. 侧边栏数据成功生成。')) } else { themeConfig.sidebar = 'auto' log(chalk.yellow('warning: fail to add sidebar data, switch to "auto". 未能添加侧边栏数据,将切换为“auto”。')) } } // 分类页 if (themeConfig.category !== false) { createPage(sourceDir, 'categoriesPage') } else { deletePage(sourceDir, 'categoriesPage') } // 标签页 if (themeConfig.tag !== false) { createPage(sourceDir, 'tagsPage') } else { deletePage(sourceDir, 'tagsPage') } // 归档页 if (themeConfig.archive !== false) { createPage(sourceDir, 'archivesPage') } else { deletePage(sourceDir, 'archivesPage') } // resolve algolia const isAlgoliaSearch = ( themeConfig.algolia || Object .keys(siteConfig.locales && themeConfig.locales || {}) .some(base => themeConfig.locales[base].algolia) ) const enableSmoothScroll = themeConfig.smoothScroll === true return { alias () { return { '@AlgoliaSearchBox': isAlgoliaSearch ? path.resolve(__dirname, 'components/AlgoliaSearchBox.vue') : path.resolve(__dirname, 'noopModule.js') } }, plugins: [ ['@vuepress/active-header-links', options.activeHeaderLinks], '@vuepress/search', '@vuepress/plugin-nprogress', ['smooth-scroll', enableSmoothScroll], ['container', { type: 'note', defaultTitle: { '/': '笔记', '/en/': 'NOTE' } }], ['container', { type: 'tip', defaultTitle: { '/': '提示', '/en/': 'TIP' } }], ['container', { type: 'warning', defaultTitle: { '/': '注意', '/en/': 'WARNING' } }], ['container', { type: 'danger', defaultTitle: { '/': '警告', '/en/': 'WARNING' } }], ['container', { type: 'right', defaultTitle: '' }], ['container', { type: 'theorem', before: info => `

${info}

`, after: '
' }], ['container', { type: 'details', before: info => `
${info ? `${info}` : ''}\n`, after: () => '
\n', defaultTitle: { '/': '点击查看', '/en/': 'DETAILS' } }], // 内容居中容器 ['container', { type: 'center', before: info => `
`, after: () => '
' }], // 卡片列表 [ 'container', { type: CARD_LIST, render: (tokens, idx) => { // tokens 是整个md文件的虚拟dom结构数组 // idx 是tokens中':::' 所在的索引,而且是当前指定type的':::',分别有开始和结束两次的idx // if (tokens[idx].nesting === 1) { // 开头的 ':::' 标记 // } else { // 结束的 ':::' 标记 // } // 注意:修改这里面的代码后需要在md文件保存一下才会重新执行渲染 return renderCardList(tokens, idx, CARD_LIST) } }, ], // 图文卡片列表 [ 'container', { type: CARD_IMG_LIST, render: (tokens, idx) => { return renderCardList(tokens, idx, CARD_IMG_LIST) } }, ], ] } } // 渲染md容器的卡片列表 function renderCardList (tokens, idx, type) { const END_TYPE = `container_${type}_close`, _tokens$idx = tokens[idx], nesting = _tokens$idx.nesting, info = _tokens$idx.info; if (nesting === 1) { // 渲染开头的 ':::' 标记 let yamlStr = ''; for (let i = idx; i < tokens.length; i++) { let _tokens$i = tokens[i], type = _tokens$i.type, content = _tokens$i.content, _info = _tokens$i.info; if (type === END_TYPE) break; // 遇到结束的 ':::' 时 if (!content) continue; if (type === 'fence' && _info === 'yaml') { // 是代码块类型,并且是yaml代码 yamlStr = content } } if (yamlStr) { // 正确解析出yaml字符串后 const dataObj = yaml.safeLoad(yamlStr) // 将yaml字符串解析成js对象 let dataList = [] if (dataObj) { // 正确解析出数据对象 dataList = Array.isArray(dataObj) ? dataObj : dataObj.list } if (dataList && dataList.length) { // 有列表数据 // 每行显示几个 let row = Number(info.split(' ').pop()) if (!row || row > 4 || row < 1) { row = 3 // 默认 3 } let listDOM = '' if (type === CARD_LIST) { // 普通卡片列表 listDOM = getCardListDOM(dataList, row) } else if (type === CARD_IMG_LIST) { // 卡片图片列表 listDOM = getCardImgListDOM(dataList, row) } return `
${listDOM}
` } } } else { // 渲染':::' 结尾 return '
' } } // 将数据解析成DOM结构 - 普通卡片列表 function getCardListDOM (dataList, row) { let listDOM = '' dataList.forEach(item => { listDOM += ` <${item.link ? 'a href="' + item.link + '" target="_blank"' : 'span'} class="card-item ${row ? 'row-' + row : ''}" style="${item.bgColor ? 'background-color:' + item.bgColor + ';--randomColor:' + item.bgColor + ';' : '--randomColor: var(--bodyBg);'}${item.textColor ? 'color:' + item.textColor + ';' : ''}" > ${item.avatar ? '' : ''}

${item.name}

${item.desc}

` }) return listDOM } // 将数据解析成DOM结构 - 图文卡片列表 function getCardImgListDOM (dataList, row) { let listDOM = '' dataList.forEach(item => { listDOM += `

${item.name}

${item.desc ? `

${item.desc}

` : ''}
${item.avatar || item.author ? ``: ''}
` }) return listDOM } // 添加base路径 function withBase (path) { if (base && path.charAt(0) === '/') { return base + path.slice(1); } else { return path; } }