239 lines
10 KiB
JavaScript
239 lines
10 KiB
JavaScript
// mods
|
|
import {existsSync} from 'node:fs';
|
|
import {dirname, resolve} from 'node:path';
|
|
import {fileURLToPath} from 'node:url';
|
|
|
|
import isEmpty from 'lodash-es/isEmpty.js';
|
|
import merge from 'lodash-es/merge.js';
|
|
import Debug from 'debug';
|
|
|
|
import {defineConfigWithTheme} from 'vitepress';
|
|
|
|
// utils
|
|
import {default as createContainer} from './utils/create-container.js';
|
|
import {default as getBaseUrl} from './utils/get-base-url.js';
|
|
import {default as getContributors} from './utils/get-contributors.js';
|
|
import {default as getGaHeaders} from './utils/get-ga-headers.js';
|
|
import {default as getHubspotHeaders} from './utils/get-hubspot-headers.js';
|
|
import {default as getTags} from './utils/get-tags.js';
|
|
import {default as normalizeMVB} from './utils/normalize-mvb.js';
|
|
import {default as parseLayouts} from './utils/parse-layouts.js';
|
|
import {default as traverseUp} from './utils/traverse-up.js';
|
|
|
|
// node/plugins
|
|
import {default as addContributors} from './node/add-contributors.js';
|
|
import {default as addLayoutsPlugin} from './vite/add-layout-components-plugin.js';
|
|
import {default as addMetadata} from './node/add-metadata.js';
|
|
import {default as augmentAuthors} from './node/augment-authors.js';
|
|
import {default as buildCollections} from './node/build-collections.js';
|
|
import {default as normalizeFrontmatter} from './node/normalize-frontmatter.js';
|
|
import {default as normalizeLegacyFrontmatter} from './node/normalize-legacy-frontmatter.js';
|
|
import {default as parseCollections} from './node/parse-collections.js';
|
|
import {default as generateFeeds} from './node/generate-feeds.js';
|
|
import {default as generateRobotsTxt} from './node/generate-robots.js';
|
|
import {default as linkOverridePlugin} from './markdown/link-override-plugin.js';
|
|
import {tabsMarkdownPlugin} from 'vitepress-plugin-tabs';
|
|
import {default as tabsMarkdownOverridePlugin} from './markdown/tabs-override-plugin.js';
|
|
import {default as urlLoader} from './vite/url-loader.js';
|
|
|
|
// vitepress patches
|
|
import {default as patchVPMenuColumnsPlugin} from './vite/patch-vp-menu-columns-plugin.js';
|
|
import {default as patchVPUseSidebarControl} from './vite/patch-vp-use-sidebar-control.js';
|
|
|
|
// configsets
|
|
import {default as baseConfig} from './config/defaults.js';
|
|
import {default as lando3BaseConfig} from './config/landov3.js';
|
|
import {default as lando4BaseConfig} from './config/landov4.js';
|
|
|
|
export async function defineConfig(userConfig = {}, defaults = {}) {
|
|
const debug = Debug('@lando/vpltheme'); // eslint-disable-line
|
|
|
|
// theme root
|
|
userConfig.themeRoot = dirname(fileURLToPath(import.meta.url));
|
|
|
|
// prefer landov4 if defaults not set
|
|
if (isEmpty(userConfig.defaults) && userConfig.landoDocs === 4) {
|
|
debug('no user defaults set, using lando v4 defaults');
|
|
defaults = lando4BaseConfig(userConfig);
|
|
// ditto but for lando v3
|
|
} else if (isEmpty(userConfig.defaults) && userConfig.landoDocs === 3) {
|
|
debug('no user defaults set, using lando v3 defaults');
|
|
defaults = lando3BaseConfig(userConfig);
|
|
// Same as above but for legacy things
|
|
} else if (isEmpty(userConfig.defaults) && (userConfig.landoDocs || userConfig.lando)) {
|
|
debug('no user defaults set, using lando v3 defaults');
|
|
defaults = lando3BaseConfig(userConfig);
|
|
// Otherwise if we are empty then just set to defaults
|
|
} else if (isEmpty(userConfig.defaults)) {
|
|
debug('no user defaults set, using theme defaults');
|
|
defaults = baseConfig(userConfig);
|
|
}
|
|
|
|
// merge config sources
|
|
const config = merge({}, defaults, userConfig);
|
|
// log
|
|
debug('incoming vitepress configuration %O', config);
|
|
|
|
// normalize mvb stuff as needed
|
|
if (config?.themeConfig.multiVersionBuild) {
|
|
config.themeConfig.multiVersionBuild = normalizeMVB({...config.themeConfig.multiVersionBuild, siteBase: config.base});
|
|
debug('normalized mvb config to %o', config.themeConfig.multiVersionBuild);
|
|
}
|
|
|
|
// get git root if its not defined
|
|
if (!config.gitRoot) {
|
|
const gitDir = traverseUp(['.git'], resolve(config.themeRoot, '..')).find(dir => existsSync(dir));
|
|
config.gitRoot = gitDir ? resolve(gitDir, '..') : config.themeRoot;
|
|
debug('automatically set gitRoot to %o', config.gitRoot);
|
|
}
|
|
|
|
// If we want to show the shared navbar then lets add it to the begining of the navbar
|
|
if (Array.isArray(config?.themeConfig?.sharedNav)) {
|
|
config.themeConfig.nav = config.themeConfig.sharedNav.concat(config.themeConfig.nav);
|
|
debug('prepended shared navbar to user specified navbar with %o', config.themeConfig.sharedNav);
|
|
}
|
|
|
|
// explode
|
|
const {buildEnd, markdown, themeConfig, transformPageData, sitemap, vite} = config;
|
|
|
|
// normalize id
|
|
if (typeof themeConfig.internalDomain === 'string') themeConfig.internalDomain = [themeConfig.internalDomain];
|
|
if (typeof themeConfig.internalDomains === 'string') themeConfig.internalDomains = [themeConfig.internalDomains];
|
|
themeConfig.internalDomains = [...themeConfig.internalDomain, ...themeConfig.internalDomains];
|
|
|
|
// normalize contribs
|
|
if (themeConfig.contributors === true) themeConfig.contributors = baseConfig.themeConfig.contributors;
|
|
|
|
// normalize layouts
|
|
if (Object.keys(themeConfig.layouts).length > 0) themeConfig.layouts = parseLayouts(themeConfig.layouts);
|
|
|
|
// normalize sitemap
|
|
if (!sitemap.hostname && themeConfig?.autometa?.canonicalUrl) sitemap.hostname = themeConfig.autometa.canonicalUrl;
|
|
|
|
// attempt to set a baseurl
|
|
if (!config.baseUrl) config.baseUrl = getBaseUrl() ?? config.basethemeConfig?.autometa?.canonicalUrl ?? sitemap.hostname;
|
|
|
|
// extract
|
|
const {containers, contributors, ga, hubspot, internalDomains, layouts} = themeConfig;
|
|
|
|
// debug here so it doesnt print like 10 times
|
|
for (const [name, opts] of Object.entries(containers)) {
|
|
debug('added custom markdown container %o with config %o', name, opts);
|
|
}
|
|
|
|
// vite aliases
|
|
vite.resolve.alias.push(...[
|
|
{find: /^.*\/VPAlgoliaSearchBox\.vue$/, replacement: fileURLToPath(new URL('./components/VPLAlgoliaSearchBox.vue', import.meta.url))},
|
|
{find: /^.*\/VPDocFooter\.vue$/, replacement: fileURLToPath(new URL('./components/VPLDocFooter.vue', import.meta.url))},
|
|
{find: /^.*\/VPLink\.vue$/, replacement: fileURLToPath(new URL('./components/VPLLink.vue', import.meta.url))},
|
|
{find: /^.*\/VPMenuGroup\.vue$/, replacement: fileURLToPath(new URL('./components/VPLMenuGroup.vue', import.meta.url))},
|
|
{find: /^.*\/VPNavBarMenuGroup\.vue$/, replacement: fileURLToPath(new URL('./components/VPLNavBarMenuGroup.vue', import.meta.url))},
|
|
{find: /^.*\/VPTeamMembersItem\.vue$/, replacement: fileURLToPath(new URL('./components/VPLTeamMembersItem.vue', import.meta.url))},
|
|
]);
|
|
|
|
// plguins
|
|
vite.plugins.push(...[
|
|
addLayoutsPlugin(layouts, {debug: debug.extend('vite-plugin')}),
|
|
patchVPMenuColumnsPlugin({debug: debug.extend('vitepress-patcher')}),
|
|
patchVPUseSidebarControl({debug: debug.extend('vitepress-patcher')}),
|
|
urlLoader({debug: debug.extend('url-loader')}),
|
|
]);
|
|
|
|
// deps
|
|
vite.optimizeDeps.exclude.push('fsevents', '@lando/vitepress-theme-default-plus');
|
|
// ssr
|
|
vite.ssr.noExternal.push('@lando/vitepress-theme-default-plus');
|
|
|
|
// debug
|
|
debug('added vite resolver config %O', vite.resolve);
|
|
debug('added vite plugins %O', vite.plugins);
|
|
debug('added vite optimizeDeps config %O', vite.optimizeDeps);
|
|
debug('added vite ssr config %O', vite.ssr);
|
|
|
|
// markdown plugins
|
|
markdown.config = md => {
|
|
// add custom markdown containers, including tabs
|
|
for (const [name, opts] of Object.entries(containers)) {
|
|
md.use(...createContainer(name, opts, md));
|
|
}
|
|
// add tabs plugin
|
|
md.use(tabsMarkdownPlugin);
|
|
// override the tabs container so we can inject styling
|
|
md.use(tabsMarkdownOverridePlugin, {debug: debug.extend('markdown-plugin')});
|
|
// override the link plugin so it can handle internal domains
|
|
md.use(linkOverridePlugin, {
|
|
target: '_blank',
|
|
rel: 'noreferrer',
|
|
...markdown.externalLinks,
|
|
},
|
|
config.base,
|
|
internalDomains,
|
|
debug.extend('markdown-plugin'),
|
|
);
|
|
};
|
|
|
|
// add google analytics
|
|
if (ga !== false && ga.id) {
|
|
config.head.push(...getGaHeaders(ga.id));
|
|
debug('added google analytics/gtm tracking with %o', ga);
|
|
}
|
|
|
|
// add hubspot
|
|
if (hubspot !== false && hubspot.id) {
|
|
config.head.push(...getHubspotHeaders(hubspot.id));
|
|
debug('added hubspot tracking with %o', hubspot);
|
|
}
|
|
|
|
// get full team info
|
|
const copts = {debug: debug.extend('get-contribs'), paths: []};
|
|
const team = contributors !== false ? await getContributors(config.gitRoot, contributors, copts) : [];
|
|
debug('discovered full team info %o', team);
|
|
|
|
// get full version alias information but let this fail
|
|
try {
|
|
const tags = await getTags(config.gitRoot, undefined, {debug: debug.extend('get-tags')});
|
|
themeConfig.versions = tags.aliases ?? {};
|
|
debug('discovered version aliases %o', config.versions);
|
|
} catch (error) {
|
|
debug('unable to get version alias information with error %o', error);
|
|
}
|
|
|
|
// build robots.txt and rssfeed
|
|
config.buildEnd = async siteConfig => {
|
|
// generate robots txt
|
|
await generateRobotsTxt(siteConfig, {debug: debug.extend('generate-robots')});
|
|
// generate rss feeds
|
|
await generateFeeds(siteConfig, {debug: debug.extend('generate-feeds')});
|
|
|
|
// run any user specified transformPageData if its a function
|
|
if (buildEnd && typeof buildEnd === 'function') {
|
|
await buildEnd(siteConfig, {debug: debug.extend('user-build-end')});
|
|
}
|
|
};
|
|
|
|
// augment pages with additional data
|
|
config.transformPageData = async (pageData, {siteConfig}) => {
|
|
// make sure siteConfig.collections exists and is populated
|
|
await buildCollections(siteConfig, {debug: debug.extend('build-collections')});
|
|
// normalize legacy frontmatter
|
|
await normalizeLegacyFrontmatter(pageData, {siteConfig, debug: debug.extend('page-data')});
|
|
// normalize frontmatter
|
|
await normalizeFrontmatter(pageData, {siteConfig, debug: debug.extend('page-data')});
|
|
// add contributor information
|
|
await addContributors(pageData, {siteConfig, debug: debug.extend('page-data')});
|
|
// add metadata information
|
|
await addMetadata(pageData, {siteConfig, debug: debug.extend('page-data')});
|
|
// parse collections
|
|
await parseCollections(pageData, {siteConfig, debug: debug.extend('page-data')});
|
|
// normalize authors
|
|
await augmentAuthors(pageData, {team, debug: debug.extend('page-data')});
|
|
|
|
// run any user specified transformPageData if its a function
|
|
if (transformPageData && typeof transformPageData === 'function') {
|
|
await transformPageData(pageData, {siteConfig, debug: debug.extend('user-transform-page-data')});
|
|
}
|
|
};
|
|
|
|
return defineConfigWithTheme(config);
|
|
}
|