The code sample is missing${srcMsg}
`); + const srcMsg = `The code sample is missing${src ? ` for\n${src}` : '.'}`; + this.setCodeHtml(htmlFromStringKnownToSatisfyTypeContract( + `${htmlEscape(srcMsg)}
`, 'message is properly escaped')); } /** Sets the innerHTML of the code container to the provided code string. */ - private setCodeHtml(formattedCode: string) { + private setCodeHtml(formattedCode: TrustedHTML) { // **Security:** Code example content is provided by docs authors and as such its considered to // be safe for innerHTML purposes. - this.codeContainer.nativeElement.innerHTML = formattedCode; + this.codeContainer.nativeElement.innerHTML = unwrapHtmlForSink(formattedCode); } /** Gets the textContent of the displayed code element. */ @@ -176,10 +181,10 @@ export class CodeComponent implements OnChanges { } } -function leftAlign(text: string): string { +function leftAlign(text: TrustedHTML): TrustedHTML { let indent = Number.MAX_VALUE; - const lines = text.split('\n'); + const lines = text.toString().split('\n'); lines.forEach(line => { const lineIndent = line.search(/\S/); if (lineIndent !== -1) { @@ -187,5 +192,7 @@ function leftAlign(text: string): string { } }); - return lines.map(line => line.substr(indent)).join('\n').trim(); + return htmlFromStringKnownToSatisfyTypeContract( + lines.map(line => line.substr(indent)).join('\n').trim(), + 'safe manipulation of existing trusted HTML'); } diff --git a/aio/src/app/custom-elements/code/pretty-printer.service.ts b/aio/src/app/custom-elements/code/pretty-printer.service.ts index 0f234dd7871d..a25c05ed091f 100644 --- a/aio/src/app/custom-elements/code/pretty-printer.service.ts +++ b/aio/src/app/custom-elements/code/pretty-printer.service.ts @@ -1,11 +1,12 @@ import { Injectable } from '@angular/core'; +import { htmlFromStringKnownToSatisfyTypeContract } from 'safevalues/unsafe/reviewed'; import { from, Observable } from 'rxjs'; import { first, map, share } from 'rxjs/operators'; import { Logger } from 'app/shared/logger.service'; -type PrettyPrintOne = (code: string, language?: string, linenums?: number | boolean) => string; +type PrettyPrintOne = (code: TrustedHTML, language?: string, linenums?: number|boolean) => string; /** * Wrapper around the prettify.js library @@ -45,13 +46,14 @@ export class PrettyPrinter { * - number: do display but start at the given number * @returns Observable
- We are unable to retrieve the "${path}" page at this time.
-
+ We are unable to retrieve the "${htmlEscape(path)}" page at this time.
Please check your connection and try again later.
"+a+""; -b=b.firstChild;f&&L(b,f,!0);M({j:d,m:f,h:b,l:1,a:null,i:null,c:null,g:null});return b.innerHTML},prettyPrint:E.prettyPrint=function(a,d){function f(){for(var b=E.PR_SHOULD_USE_CONTINUATION?c.now()+250:Infinity;p