Skip to content

Commit

Permalink
feat: now uses j2html.
Browse files Browse the repository at this point in the history
  • Loading branch information
jrfaller committed Feb 1, 2024
1 parent e12bf68 commit ed303b6
Show file tree
Hide file tree
Showing 11 changed files with 386 additions and 561 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
* Native XML support
* Native YAML support
* Fix shortcuts in vanilla web diff view
* Replaced snakehtml by j2html for webdiff

## v3.0.0 (Ficus)

Expand Down
1 change: 1 addition & 0 deletions checkstyle_ignore.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,5 @@
<suppress files=".*View.java" checks="LineLength"/>
<suppress files=".*CdJdtVisitor.java" checks=".*"/>
<suppress files=".*Run.java" checks="Indentation"/>
<suppress files=".*View.java" checks=".*"/>
</suppressions>
5 changes: 1 addition & 4 deletions client.diff/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,5 @@ dependencies {
implementation 'org.slf4j:slf4j-nop:2.0.9'
implementation 'it.unimi.dsi:fastutil:8.5.12'
implementation 'com.fifesoft:rsyntaxtextarea:3.3.4'
// exclude servlet-api 2.0 because it causes a bug with spark-core
implementation('org.rendersnake:rendersnake:1.9.0') {
exclude group: 'javax.servlet', module: 'servlet-api'
}
implementation 'com.j2html:j2html:1.6.0'
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,6 @@
import com.github.gumtreediff.client.Option;
import com.github.gumtreediff.client.diff.webdiff.VanillaDiffView;

import org.rendersnake.HtmlCanvas;
import org.rendersnake.Renderable;

import java.io.File;
import java.io.IOException;
import java.io.FileWriter;
Expand Down Expand Up @@ -67,16 +64,14 @@ public void run() throws IOException {
DirectoryComparator comparator = new DirectoryComparator(opts.srcPath, opts.dstPath);
Pair<File, File> pair = comparator.getModifiedFiles().get(0);
Diff diff = getDiff(pair.first.getAbsolutePath(), pair.second.getAbsolutePath());
Renderable view = new VanillaDiffView(pair.first, pair.second, diff, true);
HtmlCanvas c = new HtmlCanvas();
view.renderOn(c);
var html = VanillaDiffView.build(pair.first, pair.second, diff, true);
if (opts.output == null) {
System.out.println(c.toHtml());
System.out.println(html.render());
}
else {
File htmlOutput = new File(opts.output);
FileWriter writer = new FileWriter(htmlOutput);
writer.write(c.toHtml());
writer.write(html.render());
writer.close();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,176 +23,128 @@
import com.github.gumtreediff.gen.TreeGenerators;
import com.github.gumtreediff.utils.Pair;
import com.github.gumtreediff.io.DirectoryComparator;
import org.rendersnake.DocType;
import org.rendersnake.HtmlCanvas;
import org.rendersnake.Renderable;

import j2html.tags.Tag;
import j2html.tags.specialized.HtmlTag;

import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.util.List;
import java.util.Set;

import static org.rendersnake.HtmlAttributesFactory.*;

public class DirectoryDiffView implements Renderable {
private DirectoryComparator comparator;

public DirectoryDiffView(DirectoryComparator comparator) throws IOException {
this.comparator = comparator;
import static j2html.TagCreator.*;

public class DirectoryDiffView {

public static HtmlTag build(DirectoryComparator comparator) {
return html(
Header.build(),
body(
div(
div(MenuBar.build()).withClass("row"),
div(
div(
div(
div(
h4(
join("Modified files ",
span("" + comparator.getModifiedFiles().size()).withClass("badge badge-secondary"))
).withClasses("card-title", "mb-0")
).withClass("card-header"),
iff(comparator.getModifiedFiles().size() > 0, ModifiedFiles.build(comparator.getModifiedFiles(), comparator))
).withClass("card")
).withClass("col")
).withClasses("row", "mt-3", "mb-3"),
div(
div(
div(
div(
h4(
join("Deleted files ",
span("" + comparator.getDeletedFiles().size()).withClasses("badge", "badge-secondary"))
).withClasses("card-title", "mb-0")
).withClasses("card-header", "bg-danger"),
iff(comparator.getDeletedFiles().size() > 0, AddedOrDeletedFiles.build(comparator.getDeletedFiles(), comparator.getSrc()))
).withClass("card")
).withClass("col"),
div(
div(
div(
h4(
join("Added files ",
span("" + comparator.getAddedFiles().size()).withClasses("badge", "badge-secondary"))
).withClasses("card-title", "mb-0")
).withClasses("card-header", "bg-success"),
iff(comparator.getAddedFiles().size() > 0, AddedOrDeletedFiles.build(comparator.getAddedFiles(), comparator.getSrc()))
).withClass("card")
).withClass("col")
).withClass("row mb-3")
).withClass("container-fluid")
)).withLang("en");
}

@Override
public void renderOn(HtmlCanvas html) throws IOException {
html
.render(DocType.HTML5)
.html(lang("en"))
.render(new Header())
.body()
.div(class_("container-fluid"))
.div(class_("row"))
.render(new MenuBar())
._div()
.div(class_("row mt-3 mb-3"))
.div(class_("col"))
.div(class_("card"))
.div(class_("card-header"))
.h4(class_("card-title mb-0"))
.write("Modified files ")
.span(class_("badge badge-secondary")).content(comparator.getModifiedFiles().size())
._h4()
._div()
.render_if(new ModifiedFiles(comparator.getModifiedFiles()), comparator.getModifiedFiles().size() > 0)
._div()
._div()
._div()
.div(class_("row mb-3"))
.div(class_("col"))
.div(class_("card"))
.div(class_("card-header bg-danger"))
.h4(class_("card-title mb-0"))
.write("Deleted files ")
.span(class_("badge badge-secondary")).content(comparator.getDeletedFiles().size())
._h4()
._div()
.render_if(new AddedOrDeletedFiles(comparator.getDeletedFiles(), comparator.getSrc()),
comparator.getDeletedFiles().size() > 0)
._div()
._div()
.div(class_("col"))
.div(class_("card"))
.div(class_("card-header bg-success"))
.h4(class_("card-title mb-0"))
.write("Added files ")
.span(class_("badge badge-secondary")).content(comparator.getAddedFiles().size())
._h4()
._div()
.render_if(new AddedOrDeletedFiles(comparator.getAddedFiles(), comparator.getDst()),
comparator.getAddedFiles().size() > 0)
._div()
._div()
._div()
._div()
._body()
._html();
}

private class ModifiedFiles implements Renderable {
private List<Pair<File, File>> files;

private ModifiedFiles(List<Pair<File, File>> files) {
this.files = files;
}

@Override
public void renderOn(HtmlCanvas html) throws IOException {
HtmlCanvas tbody = html
.table(class_("table card-table table-striped table-condensed mb-0"))
.tbody();



int id = 0;
for (Pair<File, File> file : files) {
tbody
.tr()
.td().content(comparator.getSrc().toAbsolutePath().relativize(file.first.toPath().toAbsolutePath()).toString())
.td()
.div(class_("btn-toolbar justify-content-end"))
.div(class_("btn-group"))
//TODO: integrate this with the -g option
.if_(TreeGenerators.getInstance().hasGeneratorForFile(file.first.getAbsolutePath()))
.a(class_("btn btn-primary btn-sm").href("/monaco-diff/" + id)).content("monaco")
.a(class_("btn btn-primary btn-sm").href("/vanilla-diff/" + id)).content("classic")
._if()
.a(class_("btn btn-primary btn-sm").href("/monaco-native-diff/" + id)).content("monaco-native")
.a(class_("btn btn-primary btn-sm").href("/mergely-diff/" + id)).content("mergely")
.a(class_("btn btn-primary btn-sm").href("/raw-diff/" + id)).content("raw")
._div()
._div()
._td()
._tr();
id++;
}
tbody
._tbody()
._table();
private class ModifiedFiles {

public static Tag build(List<Pair<File, File>> files, DirectoryComparator comparator) {
return table(
tbody(
each(files, (id, file) -> tr(
td(comparator.getSrc().toAbsolutePath().relativize(file.first.toPath().toAbsolutePath()).toString()),
td(
div(
div(
iff(TreeGenerators.getInstance().hasGeneratorForFile(file.first.getAbsolutePath()), join(
a("monaco").withHref("/monaco-diff/" + id).withClasses("btn", "btn-primary btn-sm"),
a("classic").withHref("/vanilla-diff/" + id).withClasses("btn", "btn-primary btn-sm")
)
),
a("monaco-native").withHref("/monaco-native-diff/" + id).withClasses("btn", "btn-primary btn-sm"),
a("mergely").withHref("/mergely-diff/" + id).withClasses("btn", "btn-primary btn-sm"),
a("raw").withHref("/raw-diff/" + id).withClasses("btn", "btn-primary btn-sm")
).withClasses("btn-group")
).withClasses("btn-toolbar", "justify-content-end")
)
))
)
).withClasses("table card-table", "table-striped", "table-condensed mb-0");
}
}

private static class AddedOrDeletedFiles implements Renderable {
private Set<File> files;
private Path root;
private static class AddedOrDeletedFiles {

private AddedOrDeletedFiles(Set<File> files, Path root) {
this.files = files;
this.root = root;
}

@Override
public void renderOn(HtmlCanvas html) throws IOException {
HtmlCanvas tbody = html
.table(class_("table card-table table-striped table-condensed mb-0"))
.tbody();
for (File file : files) {
tbody
.tr()
.td().content(root.relativize(file.toPath()).toString())
._tr();
}
tbody
._tbody()
._table();
public static Tag build(Set<File> files, Path root) {
return table(
tbody(
each(files, file -> tr(td(root.relativize(file.toPath()).toString())))
)
).withClasses("table", "card-table", "table-striped", "table-condensed mb-0");
}
}

private static class Header implements Renderable {
@Override
public void renderOn(HtmlCanvas html) throws IOException {
html
.head()
.meta(charset("utf8"))
.meta(name("viewport").content("width=device-width, initial-scale=1.0"))
.title().content("GumTree")
.macros().stylesheet(WebDiff.BOOTSTRAP_CSS_URL)
.macros().javascript(WebDiff.JQUERY_JS_URL)
.macros().javascript(WebDiff.BOOTSTRAP_JS_URL)
.macros().javascript("/dist/shortcuts.js")
._head();
private static class Header {

public static Tag build() {
return head(
meta().withCharset("utf8"),
meta().withName("viewport").withContent("width=device-width, initial-scale=1.0"),
title("GumTree"),
link().withRel("stylesheet").withType("text/css").withHref(WebDiff.BOOTSTRAP_CSS_URL),
script().withType("text/javascript").withSrc(WebDiff.BOOTSTRAP_JS_URL),
script().withType("text/javascript").withSrc("/dist/shortcuts.js")
);
}
}

private static class MenuBar implements Renderable {
@Override
public void renderOn(HtmlCanvas html) throws IOException {
html
.div(class_("col"))
.div(class_("btn-toolbar justify-content-end"))
.div(class_("btn-group"))
.a(class_("btn btn-default btn-sm btn-danger").href("/quit")).content("Quit")
._div()
._div()
._div();
private static class MenuBar {

public static Tag build() {
return div(
div(
div(
a("Quit").withHref("/quit").withClasses("btn btn-default", "btn-sm btn-danger")
).withClass("btn-group")
).withClasses("btn-toolbar", "justify-content-end")
).withClass("col");
}
}
}
Loading

0 comments on commit ed303b6

Please sign in to comment.