/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.zeppelin.markdown;
import static org.apache.commons.lang3.StringUtils.defaultString;
import org.parboiled.BaseParser;
import org.parboiled.Rule;
import org.parboiled.support.StringBuilderVar;
import org.pegdown.Parser;
import org.pegdown.ast.ExpImageNode;
import org.pegdown.ast.TextNode;
import org.pegdown.plugins.BlockPluginParser;
import org.pegdown.plugins.PegDownPlugins;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Map;
/**
* Pegdown plugin for YUML
*/
public class PegdownYumlPlugin extends Parser implements BlockPluginParser {
public PegdownYumlPlugin() {
super(PegdownParser.OPTIONS,
PegdownParser.PARSING_TIMEOUT_AS_MILLIS,
DefaultParseRunnerProvider);
}
public PegdownYumlPlugin(Integer options,
Long maxParsingTimeInMillis,
ParseRunnerProvider parseRunnerProvider,
PegDownPlugins plugins) {
super(options, maxParsingTimeInMillis, parseRunnerProvider, plugins);
}
public static final String TAG = "%%%";
Rule StartMarker() {
return Sequence(Spn1(), TAG, Sp(), "yuml", Sp());
}
String EndMarker() {
return TAG;
}
Rule ParameterName() {
return FirstOf("type", "style", "scale", "format", "dir");
}
Rule Body() {
return OneOrMore(TestNot(TAG), BaseParser.ANY);
}
Rule BlockRule() {
ParamVar<String, String> params = new ParamVar<String, String>();
StringBuilderVar name = new StringBuilderVar();
StringBuilderVar value = new StringBuilderVar();
StringBuilderVar body = new StringBuilderVar();
return NodeSequence(
StartMarker(),
ZeroOrMore(
Sequence(
ParameterName(), name.append(match()),
String("="),
OneOrMore(Alphanumeric()), value.append(match())),
Sp(),
params.put(name.getString(), value.getString()),
name.clear(), value.clear()),
Body(),
body.append(match()),
EndMarker(),
push(
new ExpImageNode(
"title", createYumlUrl(params.get(), body.getString()), new TextNode("")))
);
}
public static String createYumlUrl(Map<String, String> params, String body) {
StringBuilder inlined = new StringBuilder();
for (String line : body.split("\\r?\\n")) {
line = line.trim();
if (line.length() > 0) {
if (inlined.length() > 0) {
inlined.append(", ");
}
inlined.append(line);
}
}
String encodedBody = null;
try {
encodedBody = URLEncoder.encode(inlined.toString(), "UTF-8");
} catch (UnsupportedEncodingException e) {
new RuntimeException("Failed to encode YUML markdown body", e);
}
StringBuilder mergedStyle = new StringBuilder();
String style = defaultString(params.get("style"), "scruffy");
String type = defaultString(params.get("type"), "class");
String format = defaultString(params.get("format"), "svg");
mergedStyle.append(style);
if (null != params.get("dir")) {
mergedStyle.append(";dir:" + params.get("dir"));
}
if (null != params.get("scale")) {
mergedStyle.append(";scale:" + params.get("scale"));
}
return new StringBuilder()
.append("http://yuml.me/diagram/")
.append(mergedStyle.toString() + "/")
.append(type + "/")
.append(encodedBody)
.append("." + format)
.toString();
}
@Override
public Rule[] blockPluginRules() {
return new Rule[]{BlockRule()};
}
}