github.com/Racer159/jackal@v0.32.7-0.20240401174413-0bd2339e4f2e/src/internal/packager/sbom/viewer.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // SPDX-FileCopyrightText: 2021-Present The Jackal Authors 3 4 // Package sbom contains tools for generating SBOMs. 5 package sbom 6 7 import ( 8 "encoding/json" 9 "fmt" 10 "html/template" 11 12 "github.com/Racer159/jackal/src/pkg/layout" 13 "github.com/Racer159/jackal/src/pkg/transform" 14 ) 15 16 func (b *Builder) createSBOMViewerAsset(identifier string, jsonData []byte) error { 17 filename := fmt.Sprintf("sbom-viewer-%s.html", b.getNormalizedFileName(identifier)) 18 return b.createSBOMHTML(filename, "viewer/template.gohtml", jsonData) 19 } 20 21 func (b *Builder) createSBOMCompareAsset() error { 22 return b.createSBOMHTML("compare.html", "viewer/compare.gohtml", []byte{}) 23 } 24 25 func (b *Builder) createSBOMHTML(filename string, goTemplate string, jsonData []byte) error { 26 // Create the sbom viewer file for the image 27 sbomViewerFile, err := b.createSBOMFile(filename) 28 if err != nil { 29 return err 30 } 31 32 defer sbomViewerFile.Close() 33 34 // Create the sbomviewer template data 35 tplData := struct { 36 ThemeCSS template.CSS 37 ViewerCSS template.CSS 38 List template.JS 39 Data template.JS 40 LibraryJS template.JS 41 CommonJS template.JS 42 ViewerJS template.JS 43 CompareJS template.JS 44 }{ 45 ThemeCSS: b.loadFileCSS("theme.css"), 46 ViewerCSS: b.loadFileCSS("styles.css"), 47 List: template.JS(b.jsonList), 48 Data: template.JS(jsonData), 49 LibraryJS: b.loadFileJS("library.js"), 50 CommonJS: b.loadFileJS("common.js"), 51 ViewerJS: b.loadFileJS("viewer.js"), 52 CompareJS: b.loadFileJS("compare.js"), 53 } 54 55 // Render the sbomviewer template 56 tpl, err := template.ParseFS(viewerAssets, goTemplate) 57 if err != nil { 58 return err 59 } 60 61 // Write the sbomviewer template to disk 62 return tpl.Execute(sbomViewerFile, tplData) 63 } 64 65 func (b *Builder) loadFileCSS(name string) template.CSS { 66 data, _ := viewerAssets.ReadFile("viewer/" + name) 67 return template.CSS(data) 68 } 69 70 func (b *Builder) loadFileJS(name string) template.JS { 71 data, _ := viewerAssets.ReadFile("viewer/" + name) 72 return template.JS(data) 73 } 74 75 // This could be optimized, but loop over all the images and components to create a list of json files. 76 func (b *Builder) generateJSONList(componentToFiles map[string]*layout.ComponentSBOM, imageList []transform.Image) ([]byte, error) { 77 var jsonList []string 78 79 for _, refInfo := range imageList { 80 normalized := b.getNormalizedFileName(refInfo.Reference) 81 jsonList = append(jsonList, normalized) 82 } 83 84 for component := range componentToFiles { 85 normalized := b.getNormalizedFileName(fmt.Sprintf("%s%s", componentPrefix, component)) 86 jsonList = append(jsonList, normalized) 87 } 88 89 return json.Marshal(jsonList) 90 }