Skip to content

Commit

Permalink
feat: added html sanitizer for remote rendering
Browse files Browse the repository at this point in the history
  • Loading branch information
anikethsaha committed Apr 21, 2020
1 parent b2e6123 commit 1e3dd13
Show file tree
Hide file tree
Showing 8 changed files with 661 additions and 158 deletions.
1 change: 1 addition & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ module.exports = {
rules: {
'prettier/prettier': ['error'],
camelcase: ['warn'],
'no-useless-escape': ['warn'],
curly: ['error', 'all'],
'dot-notation': ['error'],
eqeqeq: ['error'],
Expand Down
749 changes: 594 additions & 155 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
]
},
"dependencies": {
"dompurify": "^2.0.8",
"marked": "^0.7.0",
"medium-zoom": "^1.0.5",
"opencollective-postinstall": "^2.0.2",
Expand Down
33 changes: 30 additions & 3 deletions packages/docsify-server-renderer/index.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,45 @@
import { readFileSync } from 'fs';
import { resolve, basename } from 'path';
import resolvePathname from 'resolve-pathname';
import { AbstractHistory } from '../../src/core/router/history/abstract';
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 resolvePathname from 'resolve-pathname';
import fetch from 'node-fetch';
import debug from 'debug';
import DOMPurify from 'dompurify';

function cwd(...args) {
return resolve(process.cwd(), ...args);
}

function isExternal(url) {
let match = url.match(
/^([^:\/?#]+:)?(?:\/\/([^\/?#]*))?([^?#]+)?(\?[^#]*)?(#.*)?/
);
if (
typeof match[1] === 'string' &&
match[1].length > 0 &&
match[1].toLowerCase() !== location.protocol
) {
return true;
}
if (
typeof match[2] === 'string' &&
match[2].length > 0 &&
match[2].replace(
new RegExp(
':(' + { 'http:': 80, 'https:': 443 }[location.protocol] + ')?$'
),
''
) !== location.host
) {
return true;
}
return false;
}

function mainTpl(config) {
let html = `<nav class="app-nav${
config.repo ? '' : ' no-badge'
Expand Down Expand Up @@ -60,6 +87,7 @@ export default class Renderer {

async renderToString(url) {
this.url = url = this.router.parse(url).path;
this.isRemoteUrl = isExternal(this.url);
const { loadSidebar, loadNavbar, coverpage } = this.config;

const mainFile = this._getPath(url);
Expand Down Expand Up @@ -95,9 +123,8 @@ export default class Renderer {
this._renderHtml('cover', await this._render(coverFile), 'cover');
}

const html = this.html;
const html = this.isRemoteUrl ? DOMPurify.sanitize(this.html) : this.html;
this.html = this.template;

return html;
}

Expand Down
5 changes: 5 additions & 0 deletions packages/docsify-server-renderer/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions packages/docsify-server-renderer/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"dependencies": {
"debug": "^4.1.1",
"docsify": "^4.11.2",
"dompurify": "^2.0.8",
"node-fetch": "^2.6.0",
"resolve-pathname": "^3.0.0"
}
Expand Down
27 changes: 27 additions & 0 deletions src/core/fetch/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,32 @@ function loadNested(path, qs, file, next, vm, first) {
).then(next, _ => loadNested(path, qs, file, next, vm));
}

function isExternal(url) {
let match = url.match(
/^([^:\/?#]+:)?(?:\/\/([^\/?#]*))?([^?#]+)?(\?[^#]*)?(#.*)?/
);
if (
typeof match[1] === 'string' &&
match[1].length > 0 &&
match[1].toLowerCase() !== location.protocol
) {
return true;
}
if (
typeof match[2] === 'string' &&
match[2].length > 0 &&
match[2].replace(
new RegExp(
':(' + { 'http:': 80, 'https:': 443 }[location.protocol] + ')?$'
),
''
) !== location.host
) {
return true;
}
return false;
}

export function fetchMixin(proto) {
let last;

Expand Down Expand Up @@ -84,6 +110,7 @@ export function fetchMixin(proto) {
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);

Expand Down
2 changes: 2 additions & 0 deletions src/core/render/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { scrollActiveSidebar } from '../event/scroll';
import { Compiler } from './compiler';
import * as tpl from './tpl';
import { prerenderEmbed } from './embed';
import DOMPurify from 'dompurify';
import tinydate from 'tinydate';

function executeScript() {
Expand Down Expand Up @@ -172,6 +173,7 @@ export function renderMixin(proto) {
},
tokens => {
html = this.compiler.compile(tokens);
html = this.isRemoteUrl ? DOMPurify.sanitize(html) : html;
callback();
next();
}
Expand Down

0 comments on commit 1e3dd13

Please sign in to comment.