New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Introduce new Renderer #1995
base: master
Are you sure you want to change the base?
Introduce new Renderer #1995
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Basically, this extension looks good to enrich GitBucket presentation.
Since this is a much big pull request, I can't review perfectly at once. So I commented based on my first impression as a first review.
|
||
trait DiffRenderer extends EnhancedRenderer { | ||
def renderDiff(oldRequest: EnhancedRenderRequest, newRequest: EnhancedRenderRequest, diffIndex: Int): Html | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure why DiffRenderer
is extending EnhancedRenderer
.
/** | ||
* New style Renderer | ||
*/ | ||
trait EnhancedRenderer { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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="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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
.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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method shold be private or protected at least.
} | ||
} | ||
|
||
def content: String = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While TODO comment is remaining, is this pull request ready to be merged?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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. |
And how did it all end? |
Introduce new rendering approach
This PR introduce
EnhancedRenderer
and some extended classes.Changes
All files rendered by
EnhancedRenderer
.Renderer
assumes 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/xxx
files can't render by browser. for example tiff file can't render byimg
tag.EnhancedRenderer
providesImageRenderer
trait. 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 extendsTextRenderer
andImageRenderer
. ForTextImageRenderer
repository viewer and diff viewer render both image and source text .Allow read file as string or binary for
EnhancedRenderer
EnhancedRenderer
can 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
RendererWrapper
wraps old-styleRenderer
to new-styleEnhancedRenderer
. So, no changes required for old-style Renderer plugins.Before submitting a pull-request to GitBucket I have first: