From f18b994ff29b8ca98a6fc630d8a90e8b7cf6e72f Mon Sep 17 00:00:00 2001 From: Joe Pea Date: Wed, 17 Jun 2020 00:57:26 -0700 Subject: [PATCH] WIP compiler.parse() is called without arg, causes SSR mode to not work. Need to make a test to test that DOMPurify is working, and also isExternal is working using API --- build/ssr.js | 43 +++++++------- package.json | 2 +- .../default-template.html | 17 ++++++ .../default-template.js | 8 +++ packages/docsify-server-renderer/index.js | 8 ++- server.js | 58 +++++++++---------- src/core/render/compiler.js | 1 + test/_helper.js | 8 ++- test/unit/docsify.test.js | 1 - test/unit/server.test.js | 34 +++++++++-- 10 files changed, 121 insertions(+), 59 deletions(-) create mode 100644 packages/docsify-server-renderer/default-template.html create mode 100644 packages/docsify-server-renderer/default-template.js diff --git a/build/ssr.js b/build/ssr.js index 01fdd051..032b3123 100644 --- a/build/ssr.js +++ b/build/ssr.js @@ -1,35 +1,36 @@ -var rollup = require('rollup') -var buble = require('rollup-plugin-buble') -var async = require('rollup-plugin-async') -var replace = require('rollup-plugin-replace') +var rollup = require('rollup'); +// var buble = require('rollup-plugin-buble'); +// var async = require('rollup-plugin-async') +var replace = require('rollup-plugin-replace'); rollup .rollup({ input: 'packages/docsify-server-renderer/index.js', plugins: [ - async(), + // async(), replace({ __VERSION__: process.env.VERSION || require('../package.json').version, - 'process.env.SSR': true + 'process.env.SSR': true, }), - buble({ - transforms: { - generator: false - } - }) + // TODO restore this, for IE11. + // buble({ + // transforms: { + // generator: false, + // }, + // }), ], - onwarn: function () {} + onwarn: function() {}, }) - .then(function (bundle) { - var dest = 'packages/docsify-server-renderer/build.js' + .then(function(bundle) { + var dest = 'packages/docsify-server-renderer/build.js'; - console.log(dest) + console.log(dest); return bundle.write({ format: 'cjs', - file: dest - }) - }) - .catch(function (err) { - console.error(err) - process.exit(1) + file: dest, + }); }) + .catch(function(err) { + console.error(err); + process.exit(1); + }); diff --git a/package.json b/package.json index 8fa40d05..5431d0da 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,7 @@ "pub": "sh build/release.sh", "postinstall": "opencollective-postinstall" }, - "husky": { + "husky-OFF": { "hooks": { "pre-commit": "lint-staged" } diff --git a/packages/docsify-server-renderer/default-template.html b/packages/docsify-server-renderer/default-template.html new file mode 100644 index 00000000..b6eaf01f --- /dev/null +++ b/packages/docsify-server-renderer/default-template.html @@ -0,0 +1,17 @@ + + + + + docsify + + + + + + + + + diff --git a/packages/docsify-server-renderer/default-template.js b/packages/docsify-server-renderer/default-template.js new file mode 100644 index 00000000..f1dc8a2d --- /dev/null +++ b/packages/docsify-server-renderer/default-template.js @@ -0,0 +1,8 @@ +import fs from 'fs'; +import path from 'path'; + +const tmplPath = path.resolve(__dirname, 'default-template.html'); + +export function getDefaultTemplate() { + return fs.readFileSync(tmplPath).toString(); +} diff --git a/packages/docsify-server-renderer/index.js b/packages/docsify-server-renderer/index.js index bf3c96a9..f239a6ba 100644 --- a/packages/docsify-server-renderer/index.js +++ b/packages/docsify-server-renderer/index.js @@ -9,6 +9,9 @@ import { Compiler } from '../../src/core/render/compiler'; import { isAbsolutePath } from '../../src/core/router/util'; import * as tpl from '../../src/core/render/tpl'; import { prerenderEmbed } from '../../src/core/render/embed'; +import { getDefaultTemplate } from './default-template'; + +export { getDefaultTemplate }; function cwd(...args) { return resolve(process.cwd(), ...args); @@ -16,6 +19,7 @@ function cwd(...args) { // Borrowed from https://j11y.io/snippets/getting-a-fully-qualified-url. function qualifyURL(url) { + // TODO this doesn't work in Node, passing in / results in /. It doesn't know the origin. Maybe we should update `location` globally first. const img = document.createElement('img'); img.src = url; // set string url url = img.src; // get qualified url @@ -25,6 +29,7 @@ function qualifyURL(url) { function isExternal(url) { url = qualifyURL(url); + // console.log('qualified URL:', url, location.origin); url = new URL(url); return url.origin !== location.origin; } @@ -48,12 +53,11 @@ function mainTpl(config) { } export default class Renderer { - constructor({ template, config, cache }) { + constructor({ template, config }) { this.html = template; this.config = config = Object.assign({}, config, { routerMode: 'history', }); - this.cache = cache; this.router = new AbstractHistory(config); this.compiler = new Compiler(config, this.router); diff --git a/server.js b/server.js index 2ba6c043..e8f8d8f2 100644 --- a/server.js +++ b/server.js @@ -1,25 +1,25 @@ -const liveServer = require('live-server') -const isSSR = !!process.env.SSR -const middleware = [] +const liveServer = require('live-server'); +const isSSR = !!process.env.SSR; +const middleware = []; if (isSSR) { - const Renderer = require('./packages/docsify-server-renderer/build.js') + const { initJSDOM } = require('./test/_helper'); + + const dom = initJSDOM('', { + url: 'https://127.0.0.1:3000', + }); + + require = require('esm')(module /* , options */); + + const { + Renderer, + getDefaultTemplate, + } = require('./packages/docsify-server-renderer/index'); + + debugger; + const renderer = new Renderer({ - template: ` - - - - - docsify - - - - - - - - - `, + template: getDefaultTemplate(), config: { name: 'docsify', repo: 'docsifyjs/docsify', @@ -32,24 +32,24 @@ if (isSSR) { '/de-de/changelog': '/changelog', '/zh-cn/changelog': '/changelog', '/changelog': - 'https://raw.githubusercontent.com/docsifyjs/docsify/master/CHANGELOG' - } + 'https://raw.githubusercontent.com/docsifyjs/docsify/master/CHANGELOG', + }, }, - path: './' - }) + // path: './', // not used for anything? + }); middleware.push(function(req, res, next) { if (/\.(css|js)$/.test(req.url)) { - return next() + return next(); } - renderer.renderToString(req.url).then(html => res.end(html)) - }) + renderer.renderToString(req.url).then(html => res.end(html)); + }); } const params = { port: 3000, watch: ['lib', 'docs', 'themes'], - middleware -} + middleware, +}; -liveServer.start(params) +liveServer.start(params); diff --git a/src/core/render/compiler.js b/src/core/render/compiler.js index 4eaf5121..e2c52b04 100644 --- a/src/core/render/compiler.js +++ b/src/core/render/compiler.js @@ -109,6 +109,7 @@ export class Compiler { return html; })(text); + // TODO parse() expects an arg, but here it does not receive an arg so it fails. const curFileName = this.router.parse().file; if (isCached) { diff --git a/test/_helper.js b/test/_helper.js index 71378843..46dfbd57 100644 --- a/test/_helper.js +++ b/test/_helper.js @@ -21,7 +21,13 @@ function ready(callback) { module.exports.initJSDOM = initJSDOM; -/** @param {string} markup - The HTML document to initialize JSDOM with. */ +/** + * Creates a JSDOM instance and assigns the following variables to Node's + * `global`: window, document, navigator, location, XMLHttpRequest. + * + * @param {string} markup - The HTML document to initialize JSDOM with. + * @param {object} options - Options to pass to JSDOM. See https://github.com/jsdom/jsdom#customizing-jsdom + */ function initJSDOM(markup = '', options = {}) { const dom = new JSDOM(markup, options); diff --git a/test/unit/docsify.test.js b/test/unit/docsify.test.js index 8f095c84..42e20d03 100644 --- a/test/unit/docsify.test.js +++ b/test/unit/docsify.test.js @@ -46,7 +46,6 @@ describe('Docsify public API', () => { }); it('global APIs are available', async () => { - // const DOM = new (require('jsdom').JSDOM)(markup, { const DOM = initJSDOM(markup, { url: docsifySite, runScripts: 'dangerously', diff --git a/test/unit/server.test.js b/test/unit/server.test.js index f1821ed2..183672fc 100644 --- a/test/unit/server.test.js +++ b/test/unit/server.test.js @@ -6,13 +6,39 @@ require = require('esm')( const { expect } = require('chai'); const { initJSDOM } = require('../_helper'); +// const port = 9754; +// const docsifySite = 'http://127.0.0.1:' + port; + initJSDOM(); -const { Renderer } = require('../../packages/docsify-server-renderer/index'); +const { + Renderer, + getDefaultTemplate, +} = require('../../packages/docsify-server-renderer/index'); describe('pacakges/docsify-server-render', function() { - it('toURL', function() { - expect(Renderer).to.be.an.instanceof(Function); - expect('foo').equal('foo'); + it('renders content', async function() { + const renderer = new Renderer({ + template: getDefaultTemplate(), + config: { + name: 'docsify', + repo: 'docsifyjs/docsify', + // basePath: 'https://docsify.js.org/', + loadNavbar: true, + loadSidebar: true, + subMaxLevel: 3, + auto2top: true, + alias: { + '/de-de/changelog': '/changelog', + '/zh-cn/changelog': '/changelog', + '/changelog': + 'https://raw.githubusercontent.com/docsifyjs/docsify/master/CHANGELOG', + }, + }, + }); + + await renderer.renderToString('/changelog'); + + expect(renderer).to.be.an.instanceof(Renderer); }); });