@@ -62,24 +62,52 @@ export var JupyterError = createFactory(JupyterErrorComponent)
6262var renderer = new ( < any > marked ) . Renderer ( ) ;
6363renderer . heading = function ( text : string , level : number ) {
6464 var escapedText = text . toLowerCase ( ) . replace ( / [ ^ \w ] + / g, '-' ) ;
65- return '<h' + level + '><a name="' +
66- escapedText +
67- '" class="anchor" href="#' +
68- escapedText +
69- '"><span class="header-link"></span></a>' +
70- text + '</h' + level + '>' ;
65+ return `<h${ level } id="${ escapedText } ">${ text } <a class="anchor-link" href="#${ escapedText } ">¶</a></h${ level } >` ;
7166}
72- // TODO: make links open new tabs
73- // links in markdown cells should open in new tabs
74- // html.find("a[href]").not('[href^="#"]').attr("target", "_blank");
7567
68+ renderer . unescape = function ( html : string ) : string {
69+ // from https://github.com/chjj/marked/blob/2b5802f258c5e23e48366f2377fbb4c807f47658/lib/marked.js#L1085
70+ return html . replace ( / & ( [ # \w ] + ) ; / g, function ( _ , n ) {
71+ n = n . toLowerCase ( ) ;
72+ if ( n === 'colon' ) return ':' ;
73+ if ( n . charAt ( 0 ) === '#' ) {
74+ return n . charAt ( 1 ) === 'x'
75+ ? String . fromCharCode ( parseInt ( n . substring ( 2 ) , 16 ) )
76+ : String . fromCharCode ( + n . substring ( 1 ) ) ;
77+ }
78+ return '' ;
79+ } ) ;
80+ }
81+
82+ renderer . check_url = function ( href : string ) : boolean {
83+ try {
84+ var prot = decodeURIComponent ( this . unescape ( href ) )
85+ . replace ( / [ ^ \w : ] / g, '' )
86+ . toLowerCase ( ) ;
87+ } catch ( e ) {
88+ return false ;
89+ }
90+ if ( prot . indexOf ( 'javascript:' ) === 0 || prot . indexOf ( 'vbscript:' ) === 0 ) {
91+ return false ;
92+ }
93+ return true ;
94+ } ;
95+
96+ renderer . link = function ( href : string , title : string , text : string ) {
97+ //modified from the mark.js source to open all urls in new tabs
98+ if ( this . options . sanitize && ! this . check_url ( href ) ) {
99+ return '' ;
100+ }
101+ return `<a href="${ href } " ${ title ? `title="${ title } "` : "" } ${ href [ 0 ] !== "#" ? "target=_blank" : "" } >${ text } </a>` ;
102+ } ;
76103
77104class MarkdownCellComponent extends BaseComponent < nbformat . MarkdownCell > {
78105 onUpdateRequest ( msg : IMessage ) : void {
79106 // replace the innerHTML of the node with the rendered markdown
80107 var t = mathjaxutils . remove_math ( this . data . source ) ;
81- marked ( t . html , { sanitize : true } , ( err : any , html : string ) => {
108+ marked ( t . html , { sanitize : true , renderer : renderer } , ( err : any , html : string ) => {
82109 this . node . innerHTML = mathjaxutils . replace_math ( html , t . math ) ;
110+ // TODO: do some serious sanitization, using, for example, the caja sanitizer
83111 MathJax . Hub . Queue ( [ "Typeset" , MathJax . Hub , this . node ] ) ;
84112 } ) ;
85113 }
0 commit comments