Skip to content

Instantly share code, notes, and snippets.

@danielbodart
Last active January 17, 2017 20:13
Show Gist options
  • Select an option

  • Save danielbodart/5db4e6a162f6934e8bcf58d30aae23b0 to your computer and use it in GitHub Desktop.

Select an option

Save danielbodart/5db4e6a162f6934e8bcf58d30aae23b0 to your computer and use it in GitHub Desktop.
Using Lagarto and csselly to do server composition (Support Server side as well as command line - for build time)
package fun;
import com.googlecode.totallylazy.Streams;
import com.googlecode.totallylazy.io.Uri;
import com.googlecode.utterlyidle.HttpHandler;
import com.googlecode.utterlyidle.Request;
import com.googlecode.utterlyidle.Response;
import com.googlecode.utterlyidle.handlers.ClientHttpHandler;
import com.googlecode.utterlyidle.html.RelativeUrlHandler;
import jodd.lagarto.dom.*;
import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static com.googlecode.totallylazy.Strings.isEmpty;
import static com.googlecode.totallylazy.collections.PersistentList.constructors.list;
import static com.googlecode.totallylazy.io.Uri.uri;
import static com.googlecode.utterlyidle.Request.get;
public class HtmlHandler implements HttpHandler {
private final HttpHandler handler;
public HtmlHandler(HttpHandler handler) {
this.handler = new RelativeUrlHandler(handler);
}
@Override
public Response handle(Request request) throws Exception {
Response response = handler.handle(request);
if (!request.uri().path().endsWith(".html")) return response;
if (request.uri().path().startsWith("/static/")) return response;
Document parent = doc(response);
process(parent);
return response.entity(parent.getHtml());
}
public static void main(String[] args) throws Exception {
if (args.length != 1) {
System.out.println("Please provide 1 argument 'path/to/src.html'");
System.exit(-1);
}
HttpHandler handler = new HtmlHandler(new ClientHttpHandler());
Response response = handler.handle(get(uri(new File(args[0]))));
Streams.copyAndClose(response.entity().inputStream(), System.out);
}
public void process(Node parent) throws Exception {
processIncludes(parent);
processDecorators(parent);
processStyle(parent);
}
private void processStyle(Node parent) throws Exception {
for (Node tag : select(parent, "style[src]")) {
Uri uri = uri(tag.getAttribute("src"));
Response response = handler.handle(get(uri));
tag.removeAttribute("src");
tag.addChild(new Text(tag.getOwnerDocument(), response.entity().toString()));
}
}
private void processIncludes(Node parent) throws Exception {
processTag(parent, "include", (link, target) -> {
// NO-OP
});
}
private void processDecorators(Node parent) throws Exception {
processTag(parent, "decorator", (decorator, target) -> {
String contentSelector = decorator.getAttribute("content");
if (isEmpty(contentSelector)) {
replaceChildren(decorator, target);
} else {
select(target, contentSelector).forEach(content -> {
replaceChildren(decorator, content);
});
}
});
}
private void replaceChildren(Node decorator, Node content) {
content.removeAllChilds();
content.addChild(decorator.getChildNodes());
}
interface TagProcessor {
void process(Node tag, Node target);
}
private void processTag(Node parent, String tagSelector, TagProcessor processor) throws Exception {
for (Node tag : select(parent, tagSelector)) {
Uri uri = uri(tag.getAttribute("src"));
String selector = tag.getAttribute("selector");
Document childDoc = doc(uri);
List<Node> childNodes = select(childDoc, selector);
for (Node childNode : childNodes) {
process(childNode);
processor.process(tag, childNode);
}
replace(tag, childNodes);
}
}
private void replace(Node old, List<Node> newNodes) {
// Fix for siblingIndex not being correctly set by Lagarto
Node parentNode = old.getParentNode();
int index = list(parentNode.getChildNodes()).indexOf(old);
parentNode.insertChild(newNodes.toArray(new Node[newNodes.size()]), index + 1);
parentNode.removeChild(index);
}
private List<Node> select(Node parent, String query) {
if (isEmpty(query)) return list(parent);
return new NodeSelector(parent).select(query);
}
private Map<Uri, Document> cache = new HashMap<>();
private Document doc(Uri uri) throws Exception {
return cache.computeIfAbsent(uri, u -> {
try {
return doc(handler.handle(get(uri)));
} catch (Exception e) {
throw new RuntimeException(e);
}
}).clone();
}
private Document doc(Response response) {
LagartoDOMBuilder builder = new LagartoDOMBuilder().
enableHtmlMode();
builder.setConfig(builder.getConfig().
setCaseSensitive(true).
setParseXmlTags(true));
return builder.
parse(response.entity().toString());
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment