import * as path from 'path' ; import { window , workspace , Disposable , StatusBarItem , StatusBarAlignment , Uri , ViewColumn , WebviewPanel , Event , EventEmitter , } from 'vscode' ; /**
 * Manages cat coding webview panels
 */ export default class JSCADPreviewPanel { /**
     * Track the currently panel. Only allow a single panel to exist at a time.
     */ public static currentPanel : JSCADPreviewPanel | undefined ; public static readonly viewType = 'jscadEditor' ; private readonly _panel : WebviewPanel ; private readonly _extensionPath : string ; private _disposables : Disposable [ ] = [ ] ; private _statusBarItem : StatusBarItem = window . createStatusBarItem ( StatusBarAlignment . Left ) ; private onDidInitializeEmitter = new EventEmitter < void > ( ) ; public static createOrShow ( extensionPath ) { const column = window . activeTextEditor ? window . activeTextEditor . viewColumn : undefined ; if ( JSCADPreviewPanel . currentPanel ) { JSCADPreviewPanel . currentPanel . _panel . reveal ( column ) ; return JSCADPreviewPanel . currentPanel ; } const panel = window . createWebviewPanel ( JSCADPreviewPanel . viewType , 'JSCAD: Preview' , column || ViewColumn . Two , { enableScripts : true } ) ; JSCADPreviewPanel . currentPanel = new JSCADPreviewPanel ( panel , extensionPath , { } ) ; return JSCADPreviewPanel . currentPanel ; } public static revive ( panel , extensionPath , state ) { console . log ( 'JSCADPreviewPanel.revive' ) ; JSCADPreviewPanel . currentPanel = new JSCADPreviewPanel ( panel , extensionPath , state ) ; return JSCADPreviewPanel . currentPanel ; } private constructor ( panel , extensionPath , state ) { this . _panel = panel ; this . _extensionPath = extensionPath ; console . log ( state ) ; this . _update ( state ) ; this . _panel . onDidDispose ( ( ) => this . dispose ( ) , null , this . _disposables ) ; this . _panel . onDidChangeViewState ( e => { console . log ( 'JSCADPreviewPanel.onDidChangeViewState' ) ; if ( this . _panel . visible ) { } } , null , this . _disposables ) ; this . _panel . webview . onDidReceiveMessage ( message => { console . log ( 'JSCACPreviewPanel: received message' , message ) ; switch ( message . command ) { case 'initialized' : console . log ( 'command: initialize' ) ; this . onDidInitializeEmitter . fire ( ) ; break ; case 'alert' : window . showErrorMessage ( message . text ) ; break ; case 'status' : this . updateStatusbar ( message . text ) ; break ; default : window . showErrorMessage ( `JSCAD: unknown command: ${ message . command }` ) ; } } , null , this . _disposables ) ; } public get onDidInitialize ( ) : Event < void > { console . log ( 'JSCADPreviewPanel.onDidInitialize' ) ; return this . onDidInitializeEmitter . event ; } public updateStatusbar ( status ) { let editor = window . activeTextEditor ; if ( ! editor ) { this . _statusBarItem . hide ( ) ; return ; } let doc = editor . document ; if ( doc . languageId === "javascript" ) { this . _statusBarItem . text = `JSCAD: ${ status }` ; this . _statusBarItem . tooltip = 'JSCAD processor status' ; this . _statusBarItem . command = 'jscadEditor.openPreview' ; this . _statusBarItem . show ( ) ; } else { this . _statusBarItem . hide ( ) ; } } public dispose ( ) { JSCADPreviewPanel . currentPanel = undefined ; this . _panel . dispose ( ) ; this . _statusBarItem . dispose ( ) ; this . onDidInitializeEmitter . dispose ( ) ; while ( this . _disposables . length ) { const x = this . _disposables . pop ( ) ; if ( x ) { x . dispose ( ) ; } } } param data param fileName public setJscadData ( data , fileName ? ) { const displayName = fileName ? path . basename ( fileName ) : '' ; this . _panel . webview . postMessage ( { command : 'setData' , data : { data , fileName } } ) ; this . _panel . title = `Preview${ fileName ? ` of ${ displayName }` : '' }` ; this . _panel . iconPath = Uri . file ( path . join ( this . _extensionPath , 'resources' , 'Icon_View_Empty.svg' ) ) ; } private _update ( state = { } ) { console . log ( 'JSCADPreviewPanel._update' ) ; this . _panel . webview . html = this . _getHtmlForWebview ( state ) ; } private _getHtmlForWebview ( state = { } ) { const jscadCoreScript = Uri . file ( path . join ( this . _extensionPath , 'media' , 'dist/jscad-web-opt.js' ) ) ; const jscadEditorScript = Uri . file ( path . join ( this . _extensionPath , 'media' , 'jscad-editor-main.js' ) ) ; const jscadEditorCSS = Uri . file ( path . join ( this . _extensionPath , 'media' , 'jscad-editor.css' ) ) ; const coreScriptUri = jscadCoreScript . with ( { scheme : 'vscode-resource' } ) ; const editorScriptUri = jscadEditorScript . with ( { scheme : 'vscode-resource' } ) ; const cssUri = jscadEditorCSS . with ( { scheme : 'vscode-resource' } ) ; const nonce = getNonce ( ) ; const config = workspace . getConfiguration ( 'jscad' ) ; const options = { defaultFaceColor : config . get ( 'defaultFaceColor' ) , } ; return `<!DOCTYPE html>
    <html>
    <head>
      <meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
      <!-- <meta http-equiv="Content-Security-Policy" content="default-src 'none'; img-src vscode-resource: https:; script-src 'nonce-${ nonce }'; style-src 'nonce-${ nonce }';"> -->
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <link rel="stylesheet" href="${ cssUri }" nonce="${ nonce }" type="text/css">
      <meta name="jscad-config" content='${ JSON . stringify ( options ) }' />
    </head>
    <body>
      <div class="jscad-container">
        <div id="header">
          <div id="errordiv"></div>
        </div>

        <div id="jscad-viewer-controls">
          <div class="jscad-viewer-button jscad-viewer-button-scene" data-action-viewport="scene" title="Reset to perspective view"></div>
          <div class="jscad-viewer-button jscad-viewer-button-top" data-action-viewport="top" title="View from top (look down Z axis)"></div>
          <div class="jscad-viewer-button jscad-viewer-button-front" data-action-viewport="front" title="View from front (look along X axis)"></div>
          <div class="jscad-viewer-button jscad-viewer-button-right" data-action-viewport="right" title="View from right (look along Y axis)"></div>
        </div>

        <!-- setup display of the viewer, i.e. canvas -->
        <div id="viewerContext"></div>

        <!-- setup display of the status, as required by OpenJSCAD.js -->
        <div id="tail" style="display: none;">
          <div id="statusdiv"></div>
        </div>
      </div>

      <script nonce="${ nonce }" src="${ coreScriptUri }"></script>
      <script nonce="${ nonce }" src="${ editorScriptUri }"></script>
    </body>

    </html>` ; } } function getNonce ( ) { let text = "" ; const possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" ; for ( let i = 0 ; i < 32 ; i ++ ) { text += possible . charAt ( Math . floor ( Math . random ( ) * possible . length ) ) ; } return text ; }