Skip to content

Commit 6cf8615

Browse files
committed
Make it work also on chromium
1 parent 7b04b6b commit 6cf8615

File tree

2 files changed

+43
-78
lines changed

2 files changed

+43
-78
lines changed

spark/src/main/java/org/apache/zeppelin/spark/SparkRInterpreter.java

Lines changed: 43 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
import java.util.Properties;
3636

3737
/**
38-
* R and SparkR interpreter.
38+
* R and SparkR interpreter with visualization support.
3939
*/
4040
public class SparkRInterpreter extends Interpreter {
4141
private static final Logger logger = LoggerFactory.getLogger(SparkRInterpreter.class);
@@ -54,14 +54,6 @@ public class SparkRInterpreter extends Interpreter {
5454
.add("spark.home",
5555
SparkInterpreter.getSystemDefault("SPARK_HOME", "spark.home", "/opt/spark"),
5656
"Spark distribution location")
57-
.add("zeppelin.R.result.width",
58-
SparkInterpreter.getSystemDefault("ZEPPELIN_R_PARAGRAPH_WIDTH",
59-
"zeppelin.R.result.width", "100%"),
60-
"")
61-
.add("zeppelin.R.result.height",
62-
SparkInterpreter.getSystemDefault("ZEPPELIN_R_PARAGRAPH_HEIGHT",
63-
"zeppelin.R.result.height", "100%"),
64-
"")
6557
.add("zeppelin.R.image.width",
6658
SparkInterpreter.getSystemDefault("ZEPPELIN_R_IMAGE_WIDTH",
6759
"zeppelin.R.image.width", "100%"),
@@ -90,32 +82,15 @@ public void open() {
9082
public InterpreterResult interpret(String lines, InterpreterContext contextInterpreter) {
9183

9284
String imageWidth = getProperty("zeppelin.R.image.width");
93-
String resultWidth = getProperty("zeppelin.R.result.width");
94-
String resultHeight = getProperty("zeppelin.R.result.height");
95-
96-
String widthScript =
97-
"this.style.width = this.contentWindow.document.body.scrollWidth + 'px';";
98-
String heightScript =
99-
"this.style.height = this.contentWindow.document.body.scrollHeight + 'px';";
10085

10186
String[] sl = lines.split("\n");
10287
if (sl[0].contains("{") && sl[0].contains("}")) {
10388
String jsonConfig = sl[0].substring(sl[0].indexOf("{"), sl[0].indexOf("}") + 1);
10489
ObjectMapper m = new ObjectMapper();
10590
try {
10691
JsonNode rootNode = m.readTree(jsonConfig);
107-
JsonNode resultWidthNode = rootNode.path("resultWidth");
108-
if (!resultWidthNode.isMissingNode()) {
109-
resultWidth = resultWidthNode.textValue();
110-
widthScript = "";
111-
}
112-
JsonNode resultHeightNode = rootNode.path("resultHeight");
113-
if (!resultHeightNode.isMissingNode()) {
114-
resultHeight = resultHeightNode.textValue();
115-
heightScript = "";
116-
}
11792
JsonNode imageWidthNode = rootNode.path("imageWidth");
118-
if (!imageWidthNode.isMissingNode()) imageWidth = imageWidthNode.textValue();
93+
if (! imageWidthNode.isMissingNode()) imageWidth = imageWidthNode.textValue();
11994
}
12095
catch (Exception e) {
12196
logger.warn("Can not parse json config: " + jsonConfig, e);
@@ -129,34 +104,14 @@ public InterpreterResult interpret(String lines, InterpreterContext contextInter
129104

130105
zeppelinR().set(".zcmd", "\n```{r " + renderOptions + "}\n" + lines + "\n```");
131106
zeppelinR().eval(".zres <- knit2html(text=.zcmd)");
132-
String htmlOut = zeppelinR().getS0(".zres");
107+
String html = zeppelinR().getS0(".zres");
133108

134-
String scaledHtml = format(htmlOut, imageWidth);
109+
html = format(html, imageWidth);
135110

136-
String html = "%html"
137-
+ " "
138-
+ "<iframe style=\"overflow:hidden;\" src=\"data:text/html;base64,"
139-
+ Base64.encodeBase64String(
140-
scaledHtml
141-
.replaceAll("src=\"//", "src=\"http://")
142-
.replaceAll("href=\"//", "href=\"http://")
143-
.getBytes("UTF-8"))
144-
+ "\""
145-
+ " "
146-
+ "frameborder=\"0\""
147-
+ " "
148-
+ "onload=\""
149-
+ heightScript
150-
+ widthScript
151-
+ "\""
152-
+ " "
153-
+ "width=\"" + resultWidth + "\""
154-
+ " "
155-
+ "height=\"" + resultHeight + "\""
156-
+ " "
157-
+ "/>";
158-
159-
return new InterpreterResult(InterpreterResult.Code.SUCCESS, html);
111+
return new InterpreterResult(
112+
InterpreterResult.Code.SUCCESS,
113+
InterpreterResult.Type.HTML,
114+
html);
160115

161116
} catch (Exception e) {
162117
logger.error("Exception while connecting to R", e);
@@ -167,21 +122,45 @@ public InterpreterResult interpret(String lines, InterpreterContext contextInter
167122
// Do nothing...
168123
}
169124
}
170-
171125
}
172126

127+
/*
128+
* Ensure we return proper HTML to be displayed in the Zeppelin UI.
129+
*/
173130
private String format(String html, String imageWidth) {
174-
Document d = Jsoup.parse(html);
175-
if ((d.getElementsByTag("p").size() == 1) && (d.getElementsByTag("img").size() == 0)) {
176-
html = html.replaceAll("<p>", "<pre>").replaceAll("</p>", "</pre>");
177-
}
131+
178132
Document document = Jsoup.parse(html);
179-
document.getElementsByTag("head").append(ZeppelinR.css());
180-
Elements images = document.getElementsByTag("img");
133+
134+
Element body = document.getElementsByTag("body").get(0);
135+
Elements images = body.getElementsByTag("img");
136+
Elements scripts = body.getElementsByTag("script");
137+
Elements paragraphs = body.getElementsByTag("p");
138+
139+
if ((paragraphs.size() == 1)
140+
&& (images.size() == 0)
141+
&& (scripts.size() == 0)
142+
) {
143+
144+
// We are here with a pure text output, let's keep format intact...
145+
146+
return html.substring(
147+
html.indexOf("<body>") + 6,
148+
html.indexOf("</body>")
149+
)
150+
.replace("<p>", "<pre style='background-color: white; border: 0px;'>")
151+
.replace("</p>", "</pre>");
152+
153+
}
154+
155+
// OK, we have more than text...
156+
181157
for (Element image : images) {
182158
image.attr("width", imageWidth);
183159
}
184-
return document.toString();
160+
161+
return body.html()
162+
.replaceAll("src=\"//", "src=\"http://")
163+
.replaceAll("href=\"//", "href=\"http://");
185164
}
186165

187166
@Override
@@ -234,8 +213,9 @@ protected static ZeppelinRFactory zeppelinR() {
234213
}
235214

236215
/**
237-
* Java Factory to support tests with Mockito
238-
* (mockito can not mock the zeppelinR final scala class).
216+
* Java Factory to support tests with Mockito.
217+
*
218+
* (Mockito can not mock the zeppelinR final scala object class).
239219
*/
240220
protected static class ZeppelinRFactory {
241221
private static ZeppelinRFactory instance;

spark/src/main/scala/org/apache/zeppelin/spark/ZeppelinR.scala

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -22,21 +22,6 @@ import org.ddahl.rscala.callback._
2222

2323
object ZeppelinR {
2424

25-
val css =
26-
"""
27-
|<style type="text/css">
28-
|* {
29-
| font-family: Monaco,Menlo,"Ubuntu Mono",Consolas,source-code-pro,monospace !important;
30-
| font-size: 12px !important;
31-
| color: rgb(33,​ 33,​ 33) !important;
32-
| line-height: 17.15px !important;
33-
|}
34-
|pre {
35-
| white-space: pre-wrap !important;
36-
|}
37-
|</script>
38-
""".stripMargin
39-
4025
private val R = RClient()
4126

4227
def open(master: String = "local[*]", sparkHome: String = "/opt/spark", sparkInterpreter: SparkInterpreter): Unit = {

0 commit comments

Comments
 (0)