import { inject } from 'inversify' ; import * as path from 'path' ; import * as querystring from 'query-string' ; import { Disposable , env , Uri , ViewColumn , Webview , WebviewPanel , workspace } from 'vscode' ; import { window } from 'vscode' ; import { ICommandManager } from '../application/types' ; import { IServiceContainer } from '../ioc/types' ; import { BranchSelection , IGitServiceFactory } from '../types' ; import { ApiController } from './apiController' ; export class HtmlViewer { private readonly disposable : Disposable [ ] = [ ] ; private readonly commandManager : ICommandManager ; private readonly htmlView : Map < string , WebviewPanel > ; constructor ( @ inject ( IServiceContainer ) private serviceContainer , @ inject ( IGitServiceFactory ) private gitServiceFactory , private extensionPath ) { this . htmlView = new Map < string , WebviewPanel > ( ) ; this . commandManager = serviceContainer . get < ICommandManager > ( ICommandManager ) ; this . disposable . push ( this . commandManager . registerCommand ( 'previewHtml' , this . onPreviewHtml ) ) ; } public dispose ( ) { this . disposable . forEach ( disposable => disposable . dispose ( ) ) ; } private onPreviewHtml = ( uri , column , title , fileName ? ) => { this . createHtmlView ( Uri . parse ( uri ) , column , title , fileName ) ; } ; private async createHtmlView ( uri , column , title , fileName ? ) { if ( this . htmlView . has ( uri . toString ( ) ) ) { const webviewPanel = this . htmlView . get ( uri . toString ( ) ) ; if ( webviewPanel ) { webviewPanel . reveal ( ) ; } return ; } const query = querystring . parse ( uri . query . toString ( ) . replace ( /&amp;/g , '%26' ) , { decode : false } ) ; const id = parseInt ( query . id ! . toString ( ) , 10 ) ; const file = decodeURIComponent ( query . file ! . toString ( ) ) ; const line = query . line ? parseInt ( query . line . toString ( ) ) : undefined ; const webviewPanel = window . createWebviewPanel ( 'gitLog' , title , column , { enableScripts : true , retainContextWhenHidden : true , } ) ; webviewPanel . iconPath = { dark : Uri . file ( `${ this . extensionPath }/images/icon-dark.svg` ) , light : Uri . file ( `${ this . extensionPath }/images/icon-light.svg` ) , } ; this . htmlView . set ( uri . toString ( ) , webviewPanel ) ; const gitService = this . gitServiceFactory . getService ( id ) ; new ApiController ( webviewPanel . webview , gitService , this . serviceContainer , this . commandManager ) ; webviewPanel . onDidDispose ( ( ) => { if ( this . htmlView . has ( uri . toString ( ) ) ) { this . htmlView . delete ( uri . toString ( ) ) ; } } ) ; let branchName = gitService . getCurrentBranch ( ) ; let branchSelection = BranchSelection . Current ; const detached = gitService . getDetachedHash ( ) ; if ( ! branchName && detached ) { branchSelection = BranchSelection . Detached ; branchName = detached ; } const settings = { id , branchName , file , line , branchSelection , } ; webviewPanel . webview . html = this . getHtmlContent ( webviewPanel . webview , settings , fileName ) ; } private getRelativeResource ( webview , relativePath ) { return webview . asWebviewUri ( Uri . file ( path . join ( this . extensionPath , relativePath ) ) ) ; } private getHtmlContent ( webview , settings , fileName ? ) { const config = workspace . getConfiguration ( 'gitHistory' ) ; return `<!DOCTYPE html>
        <html>
            <head>
                <style type="text/css"> html, body{ height:100%; width:100%; overflow:hidden; padding:0;margin:0; }</style>
                <meta http-equiv="Content-Security-Policy" content="default-src 'self' http://localhost:* http://127.0.0.1:* vscode-resource: 'unsafe-inline' 'unsafe-eval'; img-src * vscode-resource:" />
                <link rel='stylesheet' type='text/css' href='${ this . getRelativeResource ( webview , 'dist/browser/bundle.css' ) }' />
            <title>Git History</title>
            <script type="text/javascript">
                window['vscode'] = acquireVsCodeApi();
                window['extensionPath'] = ${ JSON . stringify ( this . getRelativeResource ( webview , '' ) . toString ( ) ) };
                window['configuration'] = ${ JSON . stringify ( config ) };
                window['settings'] = ${ JSON . stringify ( settings ) };
                window['locale'] = '${ env . language }';
                window['fileName'] = '${ fileName }';
            </script>
            </head>
            <body>
                <div id="root"></div>
                <script src="${ this . getRelativeResource ( webview , 'dist/browser/bundle.js' ) }"></script>
            </body>
        </html>` ; } }