import liveServer from 'live-server';
import { qualifyURL } from './packages/docsify-server-renderer/src/utils';
const isSSR = !!process.env.SSR;
const middleware = [];
const port = 3000;
main();
async function main() {
if (isSSR) {
// Using JSDom here because the server relies on a small subset of DOM APIs.
// The URL used here serves no purpose other than to give JSDOM an HTTP
// URL to operate under (it probably can be anything).
initJSDOM('', { url: 'http://127.0.0.1:' + port });
const { Renderer, getServerHTMLTemplate } = await import(
'./packages/docsify-server-renderer/index'
);
const renderer = new Renderer({
// The default template is simple, without any plugins or scripts, just docsify.js.
// template: getServerHTMLTemplate(),
template: /* html */ `
docsify
`,
config: {
name: 'docsify',
// repo: 'docsifyjs/docsify',
alias: {
'.*?/awesome':
'https://raw.githubusercontent.com/docsifyjs/awesome-docsify/master/README.md',
'.*?/changelog':
'https://raw.githubusercontent.com/docsifyjs/docsify/master/CHANGELOG.md',
'/.*/_navbar.md': '/_navbar.md',
'/es/(.*)':
'https://raw.githubusercontent.com/docsifyjs/docs-es/master/$1',
'/de-de/(.*)':
'https://raw.githubusercontent.com/docsifyjs/docs-de/master/$1',
'/ru-ru/(.*)':
'https://raw.githubusercontent.com/docsifyjs/docs-ru/master/$1',
'/zh-cn/(.*)':
'https://cdn.jsdelivr.net/gh/docsifyjs/docs-zh@master/$1',
// In SSR mode, the _sidebar fallback mechanism is not implemented,
// so without this, sub pages will show their specific sidebar
// instead of the top-level sidebar.
//
// TODO SSR needs to have the fallback mechanism too, so it matches
// with the dynamic-site behavior by default, without having to add
// this line.
'/.*/_sidebar.md': '/_sidebar.md',
},
auto2top: true,
// TODO better handling of these cases, perhaps a (sane?) default value.
// basePath: undefined, // breaks: if base path is not set while in SSR mode, code tries to operate on an undefined value and errors.
// basePath: '', // breaks: similar to undefined, server doesn't lookup file correctly.
// If this is used, then after the initial payload is sent to the
// client, the client will then make all following requests to
// docsify.js.org for dynamic markdown rendering.
// basePath: 'https://docsify.js.org/',
basePath: '/docs',
hasSSR: true,
// coverpage: true, FIXME, not working in SSR.
executeScript: true,
loadSidebar: true,
loadNavbar: true,
mergeNavbar: true,
maxLevel: 4,
subMaxLevel: 2,
search: {
noData: {
'/es/': '¡No hay resultados!',
'/de-de/': 'Keine Ergebnisse!',
'/ru-ru/': 'Никаких результатов!',
'/zh-cn/': '没有结果!',
'/': 'No results!',
},
paths: 'auto',
placeholder: {
'/es/': 'Buscar',
'/de-de/': 'Suche',
'/ru-ru/': 'Поиск',
'/zh-cn/': '搜索',
'/': 'Search',
},
pathNamespaces: ['/es', '/de-de', '/ru-ru', '/zh-cn'],
},
},
});
middleware.push(function (req, res, next) {
const url = new URL(qualifyURL(req.url));
// If the hasSSR flag is enabled, then dynamic fetches of markdown from a
// "hydrated" cilent should not be compiled to HTML.
if (url.searchParams.has('hasSSR')) {
console.log('Skipping markdown handling for already-loaded client.');
return next();
}
// Only handle markdown files or folders.
if (/(\.md|\/[^.]*)$/.test(url.pathname)) {
console.log('Render markdown to HTML on the server for file ', req.url);
// This eventually feeds through the getFileName() function in
// src/core/router/history/base.js.
renderer.renderToString(req.url).then(html => res.end(html));
return;
}
// TODO There will surely be edge cases. Add an option to force certain files?
console.log('Skipping markdown handling of file ' + req.url);
return next();
});
}
const params = {
port,
watch: ['lib', 'docs', 'themes'],
middleware,
};
liveServer.start(params);
}
async function initJSDOM(markup, options) {
const { JSDOM } = (await import('jsdom')).default;
const dom = new JSDOM(markup, options);
global.window = dom.window;
global.document = dom.window.document;
global.navigator = dom.window.navigator;
global.location = dom.window.location;
global.XMLHttpRequest = dom.window.XMLHttpRequest;
return dom;
}