Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 3427c9e

Browse files
committedJul 14, 2023
feat: add support for conditional code
Close #43
1 parent 304d5e0 commit 3427c9e

File tree

5 files changed

+149
-3
lines changed

5 files changed

+149
-3
lines changed
 

‎src/main/java/com/flowingcode/vaadin/addons/demo/SourceCodeView.java

+23-1
Original file line numberDiff line numberDiff line change
@@ -24,18 +24,28 @@
2424
import com.vaadin.flow.component.dependency.NpmPackage;
2525
import com.vaadin.flow.component.html.Div;
2626
import com.vaadin.flow.dom.Element;
27+
import elemental.json.Json;
28+
import elemental.json.JsonObject;
29+
import java.util.Map;
2730

2831
@SuppressWarnings("serial")
2932
@JsModule("./code-viewer.ts")
3033
@NpmPackage(value = "lit", version = "2.5.0")
3134
class SourceCodeView extends Div implements HasSize {
3235

36+
private final Element codeViewer;
37+
3338
public SourceCodeView(String sourceUrl) {
39+
this(sourceUrl, null);
40+
}
41+
42+
public SourceCodeView(String sourceUrl, Map<String, String> properties) {
3443
String url = translateSource(sourceUrl);
35-
Element codeViewer = new Element("code-viewer");
44+
codeViewer = new Element("code-viewer");
3645
getElement().appendChild(codeViewer);
3746
getElement().getStyle().set("display", "flex");
3847
codeViewer.getStyle().set("flex-grow", "1");
48+
setProperties(properties);
3949
addAttachListener(
4050
ev -> {
4151
codeViewer.executeJs("this.fetchContents($0,$1)", url, "java");
@@ -49,4 +59,16 @@ private static String translateSource(String url) {
4959
}
5060
return url;
5161
}
62+
63+
private void setProperties(Map<String, String> properties) {
64+
if (properties != null) {
65+
JsonObject env = Json.createObject();
66+
properties.forEach((k, v) -> {
67+
if (v != null) {
68+
env.put(k, Json.create(v));
69+
}
70+
});
71+
codeViewer.setPropertyJson("env", env);
72+
}
73+
}
5274
}

‎src/main/java/com/flowingcode/vaadin/addons/demo/SplitLayoutDemo.java

+8-1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@
2323
import com.vaadin.flow.component.Composite;
2424
import com.vaadin.flow.component.splitlayout.SplitLayout;
2525
import com.vaadin.flow.component.splitlayout.SplitLayout.Orientation;
26+
import com.vaadin.flow.server.Version;
27+
import java.util.HashMap;
28+
import java.util.Map;
2629

2730
@SuppressWarnings("serial")
2831
class SplitLayoutDemo extends Composite<SplitLayout> {
@@ -31,8 +34,12 @@ class SplitLayoutDemo extends Composite<SplitLayout> {
3134

3235
public SplitLayoutDemo(Component demo, String sourceUrl) {
3336
getContent().setOrientation(Orientation.HORIZONTAL);
34-
code = new SourceCodeView(sourceUrl);
3537

38+
Map<String, String> properties = new HashMap<>();
39+
properties.put("vaadin", VaadinVersion.getVaadinVersion());
40+
properties.put("flow", Version.getFullVersion());
41+
42+
code = new SourceCodeView(sourceUrl, properties);
3643
getContent().addToPrimary(demo);
3744
getContent().addToSecondary(code);
3845
getContent().setSizeFull();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package com.flowingcode.vaadin.addons.demo;
2+
3+
import com.vaadin.flow.server.Version;
4+
import java.util.Objects;
5+
import java.util.Properties;
6+
import org.slf4j.LoggerFactory;
7+
8+
public class VaadinVersion {
9+
10+
private VaadinVersion() {
11+
throw new UnsupportedOperationException();
12+
}
13+
14+
public static String getVaadinVersion() {
15+
try {
16+
Properties pom = new Properties();
17+
pom.load(VaadinVersion.class
18+
.getResourceAsStream("/META-INF/maven/com.vaadin/vaadin-core/pom.properties"));
19+
return Objects.requireNonNull((String) pom.get("version"));
20+
} catch (Exception e) {
21+
LoggerFactory.getLogger(Version.class.getName())
22+
.warn("Unable to determine Vaadin version number", e);
23+
return null;
24+
}
25+
}
26+
27+
}

‎src/main/resources/META-INF/resources/frontend/code-viewer.ts

+88-1
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,54 @@ pre[class*="language-"] {
244244
}
245245

246246
cleanupCode(text: string) : string {
247-
return text.split('\n').map(line=>{
247+
let lines : (string|null)[] = text.split('\n');
248+
let guards : (string|undefined)[] = [];
249+
let stack : string[] = [];
250+
251+
let __elif = (guard:(string|undefined),value:(string|undefined)) => {
252+
return guard=='isfalse' ? value : 'wastrue';
253+
};
254+
255+
let transition = (top:string, next:string) => {
256+
let result = stack.pop()==top;
257+
stack.push(result?next:'error');
258+
return result;
259+
};
260+
261+
for (let i=0;i<lines.length;i++) {
262+
let m = lines[i]!.match("^\\s*//\\s*#(?<directive>\\w+)\\s*(?<line>.*)");
263+
if (m && m.groups) {
264+
let line = m.groups.line;
265+
switch (m.groups.directive) {
266+
case 'if':
267+
stack.push('if');
268+
guards.push(this.__eval(line));
269+
lines[i]=null;
270+
break;
271+
case 'else':
272+
if (!transition('if', 'else')) break;
273+
guards.push(__elif(guards.pop(), 'istrue'));
274+
lines[i]=null;
275+
break;
276+
case 'elif':
277+
if (!transition('if', 'if')) break;
278+
guards.push(__elif(guards.pop(), this.__eval(line)));
279+
lines[i]=null;
280+
break;
281+
case 'endif':
282+
stack.pop();
283+
guards.pop();
284+
lines[i]=null;
285+
}
286+
}
287+
288+
if (!guards.every(x=>x=='istrue')) {
289+
lines[i] = null;
290+
}
291+
}
292+
293+
return lines.filter(line=>line!==null)
294+
.map(line=>{
248295
let m= line!.match("^(?<spaces>\\s*)//\\s*show-source\\s(?<line>.*)");
249296
return m?m.groups!.spaces+m.groups!.line : line!;
250297
}).filter(line=>
@@ -268,4 +315,44 @@ pre[class*="language-"] {
268315
.replace(/'/g, "&#039;");
269316
}
270317

318+
__eval(line: string) : string|undefined {
319+
let expr = line.split(' ');
320+
if (expr.length==3) {
321+
if (expr[0]!='vaadin') {
322+
return 'isfalse';
323+
}
324+
325+
let op = (a:string,b:string) => {
326+
switch (expr[1]) {
327+
case 'lt': return this.__compare(a,b)<0;
328+
case 'le': return this.__compare(a,b)<=0;
329+
case 'eq': return this.__compare(a,b)==0;
330+
case 'ge': return this.__compare(a,b)>=0;
331+
case 'gt': return this.__compare(a,b)>0;
332+
case 'ne': return this.__compare(a,b)!=0;;
333+
default: return undefined;
334+
}};
335+
336+
switch (op('23',expr[2])) {
337+
case true: return 'istrue';
338+
case false: return 'isfalse';
339+
}
340+
}
341+
return undefined;
342+
}
343+
344+
__compare(a: string, b:string) : number {
345+
let aa = a.split('.');
346+
let bb = b.split('.');
347+
for (let i=0; i<Math.min(aa.length,bb.length); i++) {
348+
let ai = parseInt(aa[i]);
349+
let bi = parseInt(bb[i]);
350+
if (ai<bi) return -1;
351+
if (ai>bi) return +1;
352+
}
353+
if (aa.length<bb.length) return -1;
354+
if (aa.length<bb.length) return +1;
355+
return 0;
356+
}
357+
271358
}

‎src/test/java/com/flowingcode/vaadin/addons/demo/SampleDemoDefault.java

+3
Original file line numberDiff line numberDiff line change
@@ -33,5 +33,8 @@ public SampleDemoDefault() {
3333
add(new Span("Demo component with defaulted @DemoSource annotation"));
3434
//show-source System.out.println("this line will be displayed in the code snippet");
3535
this.getClass(); // hide-source (this line will not be displayed in the code snippet)
36+
//#if vaadin ge 23
37+
//show-source System.out.println("conditional code for Vaadin 23+");
38+
//#endif
3639
}
3740
}

0 commit comments

Comments
 (0)
Please sign in to comment.