44 "ngSanitize" ,
55 "ui.ace" ,
66 "ngPDFViewer" ,
7+ "htmlDoc" ,
78 "pascalprecht.translate" ,
89 "admin" ,
910 ] )
@@ -2559,8 +2560,7 @@ angular
25592560 "$routeParams" ,
25602561 "$sce" ,
25612562 "$q" ,
2562- "PDFViewerService" ,
2563- function ( $scope , $http , $location , $routeParams , $sce , $q , PDFViewerService ) {
2563+ function ( $scope , $http , $location , $routeParams , $sce , $q ) {
25642564 $scope . files = [ ] ;
25652565 $scope . isMac = / M a c | i P h o n e | i P a d | i P o d / . test ( navigator . platform || navigator . userAgent ) ;
25662566 $scope . fileSearchQuery = "" ;
@@ -2843,6 +2843,18 @@ angular
28432843 ) ;
28442844 }
28452845
2846+ // Defined as methods rather than inline `showSource = !showSource` in the
2847+ // template: the toolbar and the file view sit in different child scopes,
2848+ // so an inline assignment would shadow the value on one of them instead
2849+ // of updating the controller's.
2850+ $scope . toggleSource = function ( ) {
2851+ $scope . showSource = ! $scope . showSource ;
2852+ } ;
2853+
2854+ $scope . toggleAllowScripts = function ( ) {
2855+ $scope . allowScripts = ! $scope . allowScripts ;
2856+ } ;
2857+
28462858 function getMode ( extension ) {
28472859 if ( extensionModes [ extension ] ) {
28482860 return extensionModes [ extension ] ;
@@ -2852,9 +2864,14 @@ angular
28522864
28532865 function getType ( extension ) {
28542866 if ( extension == "pdf" ) {
2855- $scope . instance = PDFViewerService . Instance ( "viewer" ) ;
28562867 return "pdf" ;
28572868 }
2869+ // Rendered as a document in a sandboxed frame rather than as source —
2870+ // see html-doc.js. "html" is reserved for markup we generated
2871+ // ourselves (rendered markdown/org) and inject directly.
2872+ if ( extension == "html" || extension == "htm" ) {
2873+ return "html-doc" ;
2874+ }
28582875 if ( extension == "md" ) {
28592876 return "md" ;
28602877 }
@@ -2975,6 +2992,20 @@ angular
29752992 $scope . url = `/api/repo/${ $scope . repoId } /file/${ encodePathForUrl (
29762993 $scope . filePath
29772994 ) } ?v=${ fileVersion } `;
2995+ // Directory the file lives in, used as the <base> for a rendered HTML
2996+ // document so its relative images/stylesheets still resolve.
2997+ const dirPath = $scope . filePath . substring (
2998+ 0 ,
2999+ $scope . filePath . lastIndexOf ( "/" ) + 1
3000+ ) ;
3001+ $scope . fileBaseUrl = `/api/repo/${ $scope . repoId } /file/${
3002+ dirPath ? encodePathForUrl ( dirPath ) : ""
3003+ } `;
3004+ $scope . showSource = false ;
3005+ // Scripts in a repository's HTML are opt-in, per file — see
3006+ // html-doc.js. Reset on navigation so trust never carries over from
3007+ // one file to the next.
3008+ $scope . allowScripts = false ;
29783009
29793010 let extension = $scope . filePath . toLowerCase ( ) ;
29803011 const extensionIndex = extension . lastIndexOf ( "." ) ;
@@ -3112,6 +3143,15 @@ angular
31123143 }
31133144 $scope . type = getType ( extension ) ;
31143145
3146+ if ( $scope . type == "pdf" ) {
3147+ // The viewer streams the file itself from $scope.url, so fetching
3148+ // the bytes again here only to hold them as a JS string wastes a
3149+ // request and a lot of memory on a large report. Content stays
3150+ // non-null so the Raw/Download actions remain available.
3151+ $scope . content = "pdf" ;
3152+ return ;
3153+ }
3154+
31153155 getContent ( $scope . filePath , $scope . file ) ;
31163156 }
31173157
0 commit comments