Rendering images Previously, viewing an image would only display the size of the binary file in bytes. This change allows common-typed images to be rendered in browser using MimeTypes for type checking. Github issue: https://github.com/google/gitiles/issues/136 Change-Id: I7d987962d6632571578af7b66db53945f219eb80
diff --git a/java/com/google/gitiles/BlobSoyData.java b/java/com/google/gitiles/BlobSoyData.java index e898101..7e96d65 100644 --- a/java/com/google/gitiles/BlobSoyData.java +++ b/java/com/google/gitiles/BlobSoyData.java
@@ -20,7 +20,9 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Strings; import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; import com.google.common.collect.Maps; +import com.google.common.io.BaseEncoding; import com.google.template.soy.data.SoyListData; import com.google.template.soy.data.SoyMapData; import java.io.IOException; @@ -57,6 +59,11 @@ */ private static final int MAX_LINE_COUNT = 50000; + /** Allowed image extensions to render */ + private static final ImmutableSet<String> ALLOWED_IMAGE_TYPES = + ImmutableSet.of( + "image/gif", "image/jpeg", "image/jpg", "image/png", "image/tiff", "image/webp"); + private final GitilesView view; private final ObjectReader reader; @@ -76,8 +83,16 @@ ObjectLoader loader = reader.open(blobId, Constants.OBJ_BLOB); String content; + String imageBlob; try { byte[] raw = loader.getCachedBytes(MAX_FILE_SIZE); + + String type = MimeTypes.getMimeType(path); + if (ALLOWED_IMAGE_TYPES.contains(type) && raw.length < MAX_FILE_SIZE) { + imageBlob = "data:" + type + ";base64," + BaseEncoding.base64().encode(raw); + } else { + imageBlob = null; + } content = (raw.length < MAX_FILE_SIZE && !RawText.isBinary(raw)) ? RawParseUtils.decode(raw) : null; if (isContentTooLargeForDisplay(content)) { @@ -87,6 +102,7 @@ throw e; } catch (LargeObjectException e) { content = null; + imageBlob = null; } if (content != null) { @@ -102,6 +118,9 @@ data.put("fileUrl", GitilesView.path().copyFrom(view).toUrl()); data.put("logUrl", GitilesView.log().copyFrom(view).toUrl()); data.put("blameUrl", GitilesView.blame().copyFrom(view).toUrl()); + if (imageBlob != null) { + data.put("imgBlob", imageBlob); + } } return data; }
diff --git a/resources/com/google/gitiles/templates/ObjectDetail.soy b/resources/com/google/gitiles/templates/ObjectDetail.soy index 054f621..5e5a3a8 100644 --- a/resources/com/google/gitiles/templates/ObjectDetail.soy +++ b/resources/com/google/gitiles/templates/ObjectDetail.soy
@@ -257,6 +257,7 @@ {template blobDetail} {@param sha: ?} /** SHA of this file's blob. */ {@param? logUrl: ?} /** optional URL to a log for this file. */ + {@param? imgBlob: ?} /** optional image blob to render. */ {@param? blameUrl: ?} /** optional URL to a blame for this file. */ {@param lines: ?} /** lines (may be empty), or null for a binary file. Each line is a list of entries with "classes" and "text" fields for pretty-printed spans. */ @@ -292,7 +293,11 @@ {/if} {else} <div class="FileContents-binary"> - {msg desc="size of binary file in bytes"}{$size}-byte binary file{/msg} + {if $imgBlob} + <img src="{$imgBlob}"/> + {else} + {msg desc="size of binary file in bytes"}{$size}-byte binary file{/msg} + {/if} </div> {/if} {/template}