diff --git a/pom.xml b/pom.xml
index 5b432f1..bd7647b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -16,7 +16,7 @@
UTF-8
1.8
1.8
- 14.8.9
+ 14.10.3
9.4.36.v20210114
@@ -155,6 +155,32 @@
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+ 3.1.2
+
+
+
+ META-INF/VAADIN/config/flow-build-info.json
+
+
+
+
+ com.vaadin
+ vaadin-maven-plugin
+ ${vaadin.version}
+
+
+
+ prepare-frontend
+
+
+
+
+
diff --git a/src/main/java/com/flowingcode/vaadin/addons/demo/SourceCodeView.java b/src/main/java/com/flowingcode/vaadin/addons/demo/SourceCodeView.java
index 73a141d..2bba1a8 100644
--- a/src/main/java/com/flowingcode/vaadin/addons/demo/SourceCodeView.java
+++ b/src/main/java/com/flowingcode/vaadin/addons/demo/SourceCodeView.java
@@ -26,18 +26,28 @@
import com.vaadin.flow.component.html.Div;
import com.vaadin.flow.dom.Element;
import com.vaadin.flow.server.VaadinService;
+import elemental.json.Json;
+import elemental.json.JsonObject;
+import java.util.Map;
@SuppressWarnings("serial")
@JsModule("./code-viewer.ts")
@NpmPackage(value = "lit", version = "2.5.0")
class SourceCodeView extends Div implements HasSize {
+ private final Element codeViewer;
+
public SourceCodeView(String sourceUrl) {
+ this(sourceUrl, null);
+ }
+
+ public SourceCodeView(String sourceUrl, Map properties) {
String url = translateSource(sourceUrl);
- Element codeViewer = new Element("code-viewer");
+ codeViewer = new Element("code-viewer");
getElement().appendChild(codeViewer);
getElement().getStyle().set("display", "flex");
codeViewer.getStyle().set("flex-grow", "1");
+ setProperties(properties);
addAttachListener(
ev -> {
codeViewer.executeJs("this.fetchContents($0,$1)", url, "java");
@@ -58,4 +68,16 @@ private static String translateSource(String url) {
}
return url;
}
+
+ private void setProperties(Map properties) {
+ if (properties != null) {
+ JsonObject env = Json.createObject();
+ properties.forEach((k, v) -> {
+ if (v != null) {
+ env.put(k, Json.create(v));
+ }
+ });
+ codeViewer.setPropertyJson("env", env);
+ }
+ }
}
diff --git a/src/main/java/com/flowingcode/vaadin/addons/demo/SplitLayoutDemo.java b/src/main/java/com/flowingcode/vaadin/addons/demo/SplitLayoutDemo.java
index 5bbe584..f9c9dc1 100644
--- a/src/main/java/com/flowingcode/vaadin/addons/demo/SplitLayoutDemo.java
+++ b/src/main/java/com/flowingcode/vaadin/addons/demo/SplitLayoutDemo.java
@@ -23,6 +23,9 @@
import com.vaadin.flow.component.Composite;
import com.vaadin.flow.component.splitlayout.SplitLayout;
import com.vaadin.flow.component.splitlayout.SplitLayout.Orientation;
+import com.vaadin.flow.server.Version;
+import java.util.HashMap;
+import java.util.Map;
@SuppressWarnings("serial")
class SplitLayoutDemo extends Composite {
@@ -31,8 +34,12 @@ class SplitLayoutDemo extends Composite {
public SplitLayoutDemo(Component demo, String sourceUrl) {
getContent().setOrientation(Orientation.HORIZONTAL);
- code = new SourceCodeView(sourceUrl);
+ Map properties = new HashMap<>();
+ properties.put("vaadin", VaadinVersion.getVaadinVersion());
+ properties.put("flow", Version.getFullVersion());
+
+ code = new SourceCodeView(sourceUrl, properties);
getContent().addToPrimary(demo);
getContent().addToSecondary(code);
getContent().setSizeFull();
diff --git a/src/main/java/com/flowingcode/vaadin/addons/demo/VaadinVersion.java b/src/main/java/com/flowingcode/vaadin/addons/demo/VaadinVersion.java
new file mode 100644
index 0000000..7cd3c49
--- /dev/null
+++ b/src/main/java/com/flowingcode/vaadin/addons/demo/VaadinVersion.java
@@ -0,0 +1,27 @@
+package com.flowingcode.vaadin.addons.demo;
+
+import com.vaadin.flow.server.Version;
+import java.util.Objects;
+import java.util.Properties;
+import org.slf4j.LoggerFactory;
+
+public class VaadinVersion {
+
+ private VaadinVersion() {
+ throw new UnsupportedOperationException();
+ }
+
+ public static String getVaadinVersion() {
+ try {
+ Properties pom = new Properties();
+ pom.load(VaadinVersion.class
+ .getResourceAsStream("/META-INF/maven/com.vaadin/vaadin-core/pom.properties"));
+ return Objects.requireNonNull((String) pom.get("version"));
+ } catch (Exception e) {
+ LoggerFactory.getLogger(Version.class.getName())
+ .warn("Unable to determine Vaadin version number", e);
+ return null;
+ }
+ }
+
+}
diff --git a/src/main/resources/META-INF/resources/frontend/code-viewer.ts b/src/main/resources/META-INF/resources/frontend/code-viewer.ts
index cb519fc..edf6418 100644
--- a/src/main/resources/META-INF/resources/frontend/code-viewer.ts
+++ b/src/main/resources/META-INF/resources/frontend/code-viewer.ts
@@ -30,6 +30,8 @@ export class CodeViewer extends LitElement {
private __license : Element[] = [];
+ env: any = {};
+
createRenderRoot() {
return this;
}
@@ -244,7 +246,57 @@ pre[class*="language-"] {
}
cleanupCode(text: string) : string {
- return text.split('\n').filter(line=>
+ let lines : (string|null)[] = text.split('\n');
+ let guards : (string|undefined)[] = [];
+ let stack : string[] = [];
+
+ let __elif = (guard:(string|undefined),value:(string|undefined)) => {
+ return guard=='isfalse' ? value : 'wastrue';
+ };
+
+ let transition = (top:string, next:string) => {
+ let result = stack.pop()==top;
+ stack.push(result?next:'error');
+ return result;
+ };
+
+ for (let i=0;i\\w+)\\s*(?.*)");
+ if (m && m.groups) {
+ let line = m.groups.line;
+ switch (m.groups.directive) {
+ case 'if':
+ stack.push('if');
+ guards.push(this.__eval(line));
+ lines[i]=null;
+ break;
+ case 'else':
+ if (!transition('if', 'else')) break;
+ guards.push(__elif(guards.pop(), 'istrue'));
+ lines[i]=null;
+ break;
+ case 'elif':
+ if (!transition('if', 'if')) break;
+ guards.push(__elif(guards.pop(), this.__eval(line)));
+ lines[i]=null;
+ break;
+ case 'endif':
+ stack.pop();
+ guards.pop();
+ lines[i]=null;
+ }
+ }
+
+ if (!guards.every(x=>x=='istrue')) {
+ lines[i] = null;
+ }
+ }
+
+ return lines.filter(line=>line!==null)
+ .map(line=>{
+ let m= line!.match("^(?\\s*)//\\s*show-source\\s(?.*)");
+ return m?m.groups!.spaces+m.groups!.line : line!;
+ }).filter(line=>
!line.match("//\\s*hide-source(\\s|$)")
&& !line.startsWith('@Route')
&& !line.startsWith('@PageTitle')
@@ -265,4 +317,45 @@ pre[class*="language-"] {
.replace(/'/g, "'");
}
+ __eval(line: string) : string|undefined {
+ let expr = line.split(' ');
+ if (expr.length==3) {
+ const value = this.env[expr[0]];
+ if (value==undefined) {
+ return 'isfalse';
+ }
+
+ let op = (a:string,b:string) => {
+ switch (expr[1]) {
+ case 'lt': return this.__compare(a,b)<0;
+ case 'le': return this.__compare(a,b)<=0;
+ case 'eq': return this.__compare(a,b)==0;
+ case 'ge': return this.__compare(a,b)>=0;
+ case 'gt': return this.__compare(a,b)>0;
+ case 'ne': return this.__compare(a,b)!=0;;
+ default: return undefined;
+ }};
+
+ switch (op(value, expr[2])) {
+ case true: return 'istrue';
+ case false: return 'isfalse';
+ }
+ }
+ return undefined;
+ }
+
+ __compare(a: string, b:string) : number {
+ let aa = a.split('.');
+ let bb = b.split('.');
+ for (let i=0; ibi) return +1;
+ }
+ if (aa.length