From 8541214c9e3b64e97469d032eaaa03993949dca4 Mon Sep 17 00:00:00 2001 From: Tobias Skarhed Date: Wed, 26 Jun 2019 13:15:45 +0200 Subject: [PATCH] Markdown: Replace rendering library (#17686) * Replace remarkable with marked * Add wrapper and options for marked --- package.json | 4 +- packages/grafana-data/src/utils/index.ts | 1 + packages/grafana-data/src/utils/markdown.ts | 20 +++++++++ public/app/app.ts | 3 ++ .../core/components/PluginHelp/PluginHelp.tsx | 6 +-- .../PanelHeader/PanelHeaderCorner.tsx | 10 +++-- public/app/features/panel/panel_ctrl.ts | 6 +-- public/app/features/users/UsersListPage.tsx | 5 +-- public/app/plugins/panel/text/module.ts | 10 ++--- public/app/plugins/panel/text2/TextPanel.tsx | 9 +--- yarn.lock | 41 +++++-------------- 11 files changed, 54 insertions(+), 61 deletions(-) create mode 100644 packages/grafana-data/src/utils/markdown.ts diff --git a/package.json b/package.json index 9d80b5d39a2..bfd01de690f 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,6 @@ "@types/react-transition-group": "2.0.16", "@types/react-virtualized": "9.18.12", "@types/react-window": "1.7.0", - "@types/remarkable": "1.7.4", "angular-mocks": "1.6.6", "autoprefixer": "9.5.0", "axios": "0.19.0", @@ -192,6 +191,7 @@ "@types/angular-route": "1.7.0", "@types/d3-scale-chromatic": "1.3.1", "@types/enzyme-adapter-react-16": "1.0.5", + "@types/marked": "0.6.5", "@types/react-redux": "^7.0.8", "@types/redux-logger": "3.0.7", "@types/reselect": "2.2.0", @@ -214,6 +214,7 @@ "immutable": "3.8.2", "jquery": "3.4.1", "lodash": "4.17.11", + "marked": "0.6.2", "moment": "2.24.0", "mousetrap": "1.6.3", "mousetrap-global-bind": "1.1.0", @@ -238,7 +239,6 @@ "redux-logger": "3.0.6", "redux-observable": "1.1.0", "redux-thunk": "2.3.0", - "remarkable": "1.7.1", "reselect": "4.0.0", "rst2html": "github:thoward/rst2html#990cb89", "rxjs": "6.4.0", diff --git a/packages/grafana-data/src/utils/index.ts b/packages/grafana-data/src/utils/index.ts index 57f9f48d8bd..0174d82b35b 100644 --- a/packages/grafana-data/src/utils/index.ts +++ b/packages/grafana-data/src/utils/index.ts @@ -1 +1,2 @@ export * from './string'; +export * from './markdown'; diff --git a/packages/grafana-data/src/utils/markdown.ts b/packages/grafana-data/src/utils/markdown.ts new file mode 100644 index 00000000000..8a0ce6c839f --- /dev/null +++ b/packages/grafana-data/src/utils/markdown.ts @@ -0,0 +1,20 @@ +import marked, { MarkedOptions } from 'marked'; + +const defaultMarkedOptions: MarkedOptions = { + renderer: new marked.Renderer(), + pedantic: false, + gfm: true, + tables: true, + sanitize: true, + smartLists: true, + smartypants: false, + xhtml: false, +}; + +export function setMarkdownOptions(optionsOverride?: MarkedOptions) { + marked.setOptions({ ...defaultMarkedOptions, ...optionsOverride }); +} + +export function renderMarkdown(str: string): string { + return marked(str); +} diff --git a/public/app/app.ts b/public/app/app.ts index 9f95634330d..bd819a7a430 100644 --- a/public/app/app.ts +++ b/public/app/app.ts @@ -36,6 +36,7 @@ import { setupAngularRoutes } from 'app/routes/routes'; import 'app/routes/GrafanaCtrl'; import 'app/features/all'; import { setLocale } from '@grafana/ui/src/utils/moment_wrapper'; +import { setMarkdownOptions } from '@grafana/data'; // import symlinked extensions const extensionsIndex = (require as any).context('.', true, /extensions\/index.ts/); @@ -70,6 +71,8 @@ export class GrafanaApp { setLocale(config.bootData.user.locale); + setMarkdownOptions({ sanitize: !config.disableSanitizeHtml }); + app.config( ( $locationProvider: angular.ILocationProvider, diff --git a/public/app/core/components/PluginHelp/PluginHelp.tsx b/public/app/core/components/PluginHelp/PluginHelp.tsx index 40aed4a6c0c..67364ea9366 100644 --- a/public/app/core/components/PluginHelp/PluginHelp.tsx +++ b/public/app/core/components/PluginHelp/PluginHelp.tsx @@ -1,6 +1,5 @@ import React, { PureComponent } from 'react'; -// @ts-ignore -import Remarkable from 'remarkable'; +import { renderMarkdown } from '@grafana/data'; import { getBackendSrv } from '@grafana/runtime'; interface Props { @@ -39,8 +38,7 @@ export class PluginHelp extends PureComponent { getBackendSrv() .get(`/api/plugins/${plugin.id}/markdown/${type}`) .then((response: string) => { - const markdown = new Remarkable(); - const helpHtml = markdown.render(response); + const helpHtml = renderMarkdown(response); if (response === '' && type === 'help') { this.setState({ diff --git a/public/app/features/dashboard/dashgrid/PanelHeader/PanelHeaderCorner.tsx b/public/app/features/dashboard/dashgrid/PanelHeader/PanelHeaderCorner.tsx index d3bd38b93d1..8aaba8bdd4a 100644 --- a/public/app/features/dashboard/dashgrid/PanelHeader/PanelHeaderCorner.tsx +++ b/public/app/features/dashboard/dashgrid/PanelHeader/PanelHeaderCorner.tsx @@ -1,5 +1,6 @@ import React, { Component } from 'react'; -import Remarkable from 'remarkable'; + +import { renderMarkdown } from '@grafana/data'; import { Tooltip, ScopedVars, DataLink } from '@grafana/ui'; import { PanelModel } from 'app/features/dashboard/state/PanelModel'; @@ -45,11 +46,12 @@ export class PanelHeaderCorner extends Component { const markdown = panel.description; const linkSrv = new LinkSrv(templateSrv, this.timeSrv); const interpolatedMarkdown = templateSrv.replace(markdown, panel.scopedVars); - const remarkableInterpolatedMarkdown = new Remarkable().render(interpolatedMarkdown); + const markedInterpolatedMarkdown = renderMarkdown(interpolatedMarkdown); return ( -
-

+

+
+ {panel.links && panel.links.length > 0 && (
    {panel.links.map((link, idx) => { diff --git a/public/app/features/panel/panel_ctrl.ts b/public/app/features/panel/panel_ctrl.ts index 52ef34b5810..473ccdbb99b 100644 --- a/public/app/features/panel/panel_ctrl.ts +++ b/public/app/features/panel/panel_ctrl.ts @@ -1,6 +1,6 @@ import _ from 'lodash'; -import Remarkable from 'remarkable'; import { sanitize, escapeHtml } from 'app/core/utils/text'; +import { renderMarkdown } from '@grafana/data'; import config from 'app/core/config'; import { profiler } from 'app/core/core'; @@ -259,8 +259,8 @@ export class PanelCtrl { const interpolatedMarkdown = templateSrv.replace(markdown, this.panel.scopedVars); let html = '
    '; - const md = new Remarkable().render(interpolatedMarkdown); - html += sanitize(md); + const md = renderMarkdown(interpolatedMarkdown); + html += config.disableSanitizeHtml ? md : sanitize(md); if (this.panel.links && this.panel.links.length > 0) { html += '