diff --git a/packages/docsify-server-renderer/index.js b/packages/docsify-server-renderer/index.js index f023b0b74..005d17a1f 100644 --- a/packages/docsify-server-renderer/index.js +++ b/packages/docsify-server-renderer/index.js @@ -123,7 +123,9 @@ export default class Renderer { this._renderHtml('cover', await this._render(coverFile), 'cover'); } - const html = this.isRemoteUrl ? DOMPurify.sanitize(this.html) : this.html; + const html = this.isRemoteUrl + ? DOMPurify.sanitize(this.html, { ADD_TAGS: ['script'] }) + : this.html; this.html = this.template; return html; } diff --git a/src/core/fetch/index.js b/src/core/fetch/index.js index 1853a0297..7a66e0a78 100644 --- a/src/core/fetch/index.js +++ b/src/core/fetch/index.js @@ -102,41 +102,50 @@ export function fetchMixin(proto) { }; proto._fetch = function(cb = noop) { - const { path, query } = this.route; - const qs = stringifyQuery(query, ['id']); - const { loadNavbar, requestHeaders, loadSidebar } = this.config; - // Abort last request - - const file = this.router.getFile(path); - const req = request(file + qs, true, requestHeaders); - - this.isRemoteUrl = isExternal(file); - // Current page is html - this.isHTML = /\.html$/g.test(file); - - // Load main content - req.then( - (text, opt) => - this._renderMain( - text, - opt, - this._loadSideAndNav(path, qs, loadSidebar, cb) - ), - _ => { - this._fetchFallbackPage(path, qs, cb) || this._fetch404(file, qs, cb); - } - ); - - // Load nav - loadNavbar && - loadNested( - path, - qs, - loadNavbar, - text => this._renderNav(text), - this, - true + const { query } = this.route; + let { path } = this.route; + + // Prevent loading remote content via URL hash + // Ex: https://foo.com/#//bar.com/file.md + if (isExternal(path)) { + history.replaceState(null, '', '#'); + this.router.normalize(); + } else { + const qs = stringifyQuery(query, ['id']); + const { loadNavbar, requestHeaders, loadSidebar } = this.config; + // Abort last request + + const file = this.router.getFile(path); + const req = request(file + qs, true, requestHeaders); + + this.isRemoteUrl = isExternal(file); + // Current page is html + this.isHTML = /\.html$/g.test(file); + + // Load main content + req.then( + (text, opt) => + this._renderMain( + text, + opt, + this._loadSideAndNav(path, qs, loadSidebar, cb) + ), + _ => { + this._fetchFallbackPage(path, qs, cb) || this._fetch404(file, qs, cb); + } ); + + // Load nav + loadNavbar && + loadNested( + path, + qs, + loadNavbar, + text => this._renderNav(text), + this, + true + ); + } }; proto._fetchCover = function() { diff --git a/src/core/render/index.js b/src/core/render/index.js index 468e281a9..35666226d 100644 --- a/src/core/render/index.js +++ b/src/core/render/index.js @@ -330,7 +330,9 @@ export function renderMixin(proto) { }, tokens => { html = this.compiler.compile(tokens); - html = this.isRemoteUrl ? DOMPurify.sanitize(html) : html; + html = this.isRemoteUrl + ? DOMPurify.sanitize(html, { ADD_TAGS: ['script'] }) + : html; callback(); next(); }