Introduce new Renderer#1995
Conversation
There was a problem hiding this comment.
I'm not sure why DiffRenderer is extending EnhancedRenderer.
| /** | ||
| * New style Renderer | ||
| */ | ||
| trait EnhancedRenderer { |
There was a problem hiding this comment.
I think it's might better that EnhancedRenderer has only renderContent method and implement the method in concrete classes. While it looks to switch diff presentation in the template by checking type of renderer, I wonder if it can be generalized instead of branching off in the template.
On the other hand, it's understandable that TextRenderer has further rendererMarkup method.
There was a problem hiding this comment.
Well... My opinion is the a parent class shouldn't know sub classes.
renderContent() isn't necessary to be implemented at EnhancedRenderer. This method should be only declared at EnhancedRenderer, and you can give implementation at TextRemderer, ImageRenderer and ObjectRenderer.
| <input type="hidden" id="lineSeparator" name="lineSeparator" value="@content.map(_.lineSeparator).getOrElse("LF")"/> | ||
| <input type="hidden" id="content" name="content" value=""/> | ||
| <input type="hidden" id="initial" value="@content.content"/> | ||
| <input type="hidden" id="initial" value="@content.map(_.content).getOrElse("")"/> |
There was a problem hiding this comment.
.getOrElse("") is unnecessary. Twirl renderes None as an empty string.
| } | ||
| } | ||
|
|
||
| def openFile[T](default: T)(f: InputStream => T): T = { |
There was a problem hiding this comment.
This method shold be private or protected at least.
| } | ||
| } | ||
|
|
||
| def content: String = { |
There was a problem hiding this comment.
This method can be implemented using contentBytes.
| val fileName = filePath.last.toLowerCase | ||
| val extension = FileUtil.getExtension(fileName) | ||
| val renderer = PluginRegistry().getRenderer(extension) | ||
| if (renderer.isInstanceOf[TextRenderer]) { |
There was a problem hiding this comment.
Basically, pattern match is better than the combination of isInstanceOf and cast, but adding a method to return TextRenderer might be more better.
| case (None, None) => { | ||
| <div>Error???</div> | ||
| } | ||
| case (Some(oldCI: ContentInfo), Some(newCI: ContentInfo)) if oldCI.renderer.isInstanceOf[DiffRenderer] && newCI.renderer.isInstanceOf[DiffRenderer] => { |
There was a problem hiding this comment.
oldCI and newCI are a little confusing because I didn't know what is CI at first. In my opinion, oldContentInfo and newContentInfo are better in this case.
| } else { | ||
| @if(diff.changeType != ChangeType.ADD){ | ||
| <div style="padding: 12px;">Not supported</div> | ||
| @* TODO: too Large check *@ |
There was a problem hiding this comment.
While TODO comment is remaining, is this pull request ready to be merged?
There was a problem hiding this comment.
Sorry, I didn't remove it. This TODO is fixed by introducing LargeFileRenderer
|
@takezoe Thanks for your review comments. Sorry for large PR. But I can't split to smaller PR. I fixed this PR with your comments except this comment. It is essential part of this PR. I think we need to discuss it carefully. I think |
| loader: ObjectLoader, | ||
| branch: String, | ||
| filePath: String | ||
| ) { |
There was a problem hiding this comment.
Basically, case classes shouldn't cause (or depend on) side effect in the constructor. These properties should be set at the outside of case classes (e.g. You can create a factory method in the companion object to do it).
This also makes possible to extract a renderer using pattern matching, not cast of the renderer property.
| /** | ||
| * New style Renderer | ||
| */ | ||
| trait EnhancedRenderer { |
There was a problem hiding this comment.
Well... My opinion is the a parent class shouldn't know sub classes.
renderContent() isn't necessary to be implemented at EnhancedRenderer. This method should be only declared at EnhancedRenderer, and you can give implementation at TextRemderer, ImageRenderer and ObjectRenderer.
| case (None, None) => { | ||
| <div>Error???</div> | ||
| } | ||
| case (Some(oldContentInfo: ContentInfo), Some(newContentInfo: ContentInfo)) if oldContentInfo.renderer.isInstanceOf[DiffRenderer] && newContentInfo.renderer.isInstanceOf[DiffRenderer] => { |
There was a problem hiding this comment.
I wonder if renderer can be extracted from ContentInfo using pattern matching, not type casting. See also above commet for ContentInfo.
|
@kounoike I added some comments to the design of your new rederer framework. I hope that you will check them. |

Introduce new rendering approach
This PR introduce
EnhancedRendererand some extended classes.Changes
All files rendered by
EnhancedRenderer.Rendererassumes used for render Markup. So, image/video/audio renderer is tricky.correct handling image files
Previously, GitBucket detects image files by MIME-type. But, some
image/xxxfiles can't render by browser. for example tiff file can't render byimgtag.EnhancedRendererprovidesImageRenderertrait. It represents "file can render by img tag".Image file is not limited to binary
For example, SVG file is text but it can rendered by img tag. So this PR introduce
TextImageRenderer. It extendsTextRendererandImageRenderer. ForTextImageRendererrepository viewer and diff viewer render both image and source text .Allow read file as string or binary for
EnhancedRendererEnhancedRenderercan read file as binary. So, it can render with format converter (for example, tiff to png).It enables direct serving image file with data-URI. It reduce number of connections.
Diffs rendered by
EnhancedRenderer.If plugin has new renderer which extends
ImageRenderer, automatically rendered with Image Diff tool.or, If renderer extends
DiffRenderer, diffs are rendered with custom diff rendering.for example: JSON diff by benjamine/JsonDiffPatch
Compatibility
The
RendererWrapperwraps old-styleRendererto new-styleEnhancedRenderer. So, no changes required for old-style Renderer plugins.Before submitting a pull-request to GitBucket I have first: