diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..9fcaa5a
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,4 @@
+# Store all text files with LF in the repository, and check them out with LF
+# on every platform. The source code viewer compares lines verbatim against
+# the expected output of the integration tests, which fails on a CRLF checkout.
+* text=auto eol=lf
diff --git a/README.md b/README.md
index 4996591..7e21369 100644
--- a/README.md
+++ b/README.md
@@ -167,7 +167,7 @@ Commonly used boilerplate code from source snippets is automatically hidden:
- `@org.junit.Ignore`
- Calls to `SourceCodeViewer.highlight`, `SourceCodeViewer.highlightOnHover` and `SourceCodeViewer.highlightOnClick`
-This feature cannot be disabled.
+This feature cannot be disabled, but a line ending with a `// show-source` comment is always rendered. The comment itself is removed, so the line is rendered as it is written.

@@ -230,8 +230,8 @@ The highlighted fragment is automatically scrolled into view.
A fragment is highlighted either by calling `SourceCodeViewer.highlight(filenameAndId)` or when clicking/hovering a component that has been configured with `SourceCodeViewer.highlightOnClick` or `SourceCodeViewer.highlightOnHover`, where `filenameAndId` is the name of the fragment. If the component is in an additional source file, `filenameAndId` can be given as a string in the format `filename#id`. If no `'#'` is present, it is assumed that the identifier corresponds to a block in the first source panel. `SourceCodeViewer.highlight(null)` turns off the highlighting.
-In the source code, a fragment is delimited by `// begin-block filenameAndId` and `// end-block` comments. Nested fragments are not supported.
-The `// begin-block` and `// end-block` comments are removed after post-processing.
+In the source code, a fragment is delimited by `// begin-block id` and `// end-block` comments. Nested fragments are not supported.
+The begin-block and end-block comments are removed after post-processing.
```
// begin-block first
@@ -245,6 +245,16 @@ The `// begin-block` and `// end-block` comments are removed after post-processi
add(other);
```
+The delimiters can also be written as block comments, which is the only option in languages that have no line comments, such as CSS.
+
+```css
+/* begin-block dashed */
+.dashed {
+ border: 1px dashed black;
+}
+/* end-block */
+```
+

diff --git a/base/pom.xml b/base/pom.xml
index 235a968..01e0df2 100644
--- a/base/pom.xml
+++ b/base/pom.xml
@@ -5,7 +5,7 @@
com.flowingcode.vaadin.addons.demo
commons-demo
- 5.4.1-SNAPSHOT
+ 5.5.0-SNAPSHOT
Commons Demo
Common classes for add-ons demo
diff --git a/base/src/main/resources/META-INF/resources/frontend/code-viewer.ts b/base/src/main/resources/META-INF/resources/frontend/code-viewer.ts
index 034d98c..7c8a5d4 100644
--- a/base/src/main/resources/META-INF/resources/frontend/code-viewer.ts
+++ b/base/src/main/resources/META-INF/resources/frontend/code-viewer.ts
@@ -338,7 +338,9 @@ pre[class*="language-"] {
return lines.filter(line=>line!==null)
.map(line=>line!)
.filter(line=>
- !line.match("//\\s*hide-source(\\s|$)")
+ //a trailing show-source comment overrides the boilerplate removal
+ line.match(/\/\/\s*show-source\s*$/)!=null
+ || (!line.match("//\\s*hide-source(\\s|$)")
&& !line.startsWith('@Route')
&& !line.startsWith('@PageTitle')
&& !line.startsWith('@SuppressWarnings')
@@ -350,10 +352,13 @@ pre[class*="language-"] {
&& line != 'import com.vaadin.flow.router.PageTitle;'
&& line != 'import com.vaadin.flow.router.Route;'
&& line != 'import com.flowingcode.vaadin.addons.demo.DemoSource;'
- && line != 'import org.junit.Ignore;'
+ && line != 'import org.junit.Ignore;')
).map(line=>{
let m= line!.match("^(?\\s*)//\\s*show-source\\s(?.*)");
- return m?m.groups!.spaces+m.groups!.line : line;
+ if (m) return m.groups!.spaces+m.groups!.line;
+ //remove a trailing show-source comment
+ const suffix = /\/\/\s*show-source\s*$/.exec(line!);
+ return suffix ? line!.slice(0,suffix.index).trimEnd() : line!;
})
.join('\n');
}
@@ -415,30 +420,57 @@ pre[class*="language-"] {
//remove trailing \n and spaces from text node i
const node = nodes[i]
if (node && node.nodeType==3) {
- node.textContent=(node.textContent as any).replaceAll(/\n[\t\x20]+$/g,'');
+ node.textContent=(node.textContent as any).replaceAll(/\n[\t\x20]*$/g,'');
}
}
-
+
+ const trimStart = (i:number) => {
+ //remove the leading \n from text node i
+ const node = nodes[i]
+ if (node && node.nodeType==3) {
+ node.textContent=(node.textContent as any).replace(/^\n/,'');
+ }
+ }
+
+ //remove the line of the delimiter at node i. When the delimiter is the first
+ //node there is no preceding text node, so the following one is trimmed instead.
+ const trimDelimiter = (i:number) => {
+ if (i>0) {
+ trimEnd(i-1);
+ } else {
+ trimStart(i+1);
+ }
+ }
+
+ //return the body of a line (//...) or block (/*...*/) comment, or undefined if the
+ //text is not a comment. Block comments are used by languages that lack line comments.
+ const commentBody = (text:string) : string|undefined => {
+ const m = text.match("^//(.*)") ?? text.match("^/\\*((?:[^*]|\\*(?!/))*)\\*/");
+ return m ? m[1] : undefined;
+ }
+
var last : string|undefined;
for (var i=0; i {
- SourceCodeViewer.highlight(null);
+ SourceCodeViewer.highlight(null); // show-source
}));
add(hl);
diff --git a/base/src/test/java/com/flowingcode/vaadin/addons/demo/it/AbstractSourceCodeViewerIT.java b/base/src/test/java/com/flowingcode/vaadin/addons/demo/it/AbstractSourceCodeViewerIT.java
index 408eef8..8e365e5 100644
--- a/base/src/test/java/com/flowingcode/vaadin/addons/demo/it/AbstractSourceCodeViewerIT.java
+++ b/base/src/test/java/com/flowingcode/vaadin/addons/demo/it/AbstractSourceCodeViewerIT.java
@@ -42,15 +42,23 @@ private String getResourceName() {
}
protected String open(String... args) {
- String resource = getResourceName();
+ return openSource(getResourceName(), "java", args);
+ }
+
+ /** Opens the stylesheet resource named after the test method. */
+ protected String openCss(String... args) {
+ return openSource(getResourceName(), "css", args);
+ }
+ private String openSource(String resource, String extension, String... args) {
if (viewer != null) {
throw new IllegalStateException();
}
String path = "com/flowingcode/vaadin/addons/demo/it/" + resource;
String params = Stream.of(args).map(Object::toString).collect(Collectors.joining(";"));
- getDriver().get(getURL(String.format("it/view/%s?src/test/resources/%s.java", params, path)));
+ getDriver()
+ .get(getURL(String.format("it/view/%s?src/test/resources/%s.%s", params, path, extension)));
viewer = $(SourceCodeViewerElement.class).waitForFirst();
return viewer.getText();
}
diff --git a/base/src/test/java/com/flowingcode/vaadin/addons/demo/it/SourceCodeViewerElement.java b/base/src/test/java/com/flowingcode/vaadin/addons/demo/it/SourceCodeViewerElement.java
index 7f5f40a..be51170 100644
--- a/base/src/test/java/com/flowingcode/vaadin/addons/demo/it/SourceCodeViewerElement.java
+++ b/base/src/test/java/com/flowingcode/vaadin/addons/demo/it/SourceCodeViewerElement.java
@@ -21,8 +21,27 @@
import com.vaadin.testbench.TestBenchElement;
import com.vaadin.testbench.elementsbase.Element;
+import org.openqa.selenium.By;
@Element("code-viewer")
public class SourceCodeViewerElement extends TestBenchElement {
-
+
+ private static final String LANGUAGE_PREFIX = "language-";
+
+ /**
+ * Returns the language that was used for formatting the source, as identified by the
+ * {@code language-} class of the rendered code, or {@code null} if there is none.
+ */
+ public String getLanguage() {
+ String className = findElement(By.tagName("code")).getAttribute("class");
+ if (className != null) {
+ for (String s : className.split("\\s+")) {
+ if (s.startsWith(LANGUAGE_PREFIX)) {
+ return s.substring(LANGUAGE_PREFIX.length());
+ }
+ }
+ }
+ return null;
+ }
+
}
diff --git a/base/src/test/java/com/flowingcode/vaadin/addons/demo/it/SourceCodeViewerIT.java b/base/src/test/java/com/flowingcode/vaadin/addons/demo/it/SourceCodeViewerIT.java
index 38121a5..6892f3b 100644
--- a/base/src/test/java/com/flowingcode/vaadin/addons/demo/it/SourceCodeViewerIT.java
+++ b/base/src/test/java/com/flowingcode/vaadin/addons/demo/it/SourceCodeViewerIT.java
@@ -39,6 +39,11 @@ public void testShowSource() {
assertEquals(expected(), open());
}
+ @Test
+ public void testShowSourceOverride() {
+ assertEquals(expected(), open());
+ }
+
@Test
public void testPackageCleanup() {
assertEquals(expected(), open());
@@ -59,4 +64,10 @@ public void testCleanupOverride() {
assertEquals(expected(), open());
}
+ @Test
+ public void testCssFragment() {
+ assertEquals(expected(), openCss());
+ assertEquals("css", viewer.getLanguage());
+ }
+
}
diff --git a/base/src/test/java/com/flowingcode/vaadin/addons/demo/it/SourceCodeViewerView.java b/base/src/test/java/com/flowingcode/vaadin/addons/demo/it/SourceCodeViewerView.java
index 248a87d..3531cae 100644
--- a/base/src/test/java/com/flowingcode/vaadin/addons/demo/it/SourceCodeViewerView.java
+++ b/base/src/test/java/com/flowingcode/vaadin/addons/demo/it/SourceCodeViewerView.java
@@ -46,7 +46,8 @@ public void setParameter(BeforeEvent event, @OptionalParameter String parameter)
}
String url = event.getLocation().getQueryParameters().getQueryString();
- add(new SourceCodeViewer(url, properties));
+ String language = url.endsWith(".css") ? "css" : "java";
+ add(new SourceCodeViewer(url, language, properties));
}
}
diff --git a/base/src/test/resources/META-INF/resources/frontend/highlight-demo.css b/base/src/test/resources/META-INF/resources/frontend/highlight-demo.css
index e80d578..ab9309e 100644
--- a/base/src/test/resources/META-INF/resources/frontend/highlight-demo.css
+++ b/base/src/test/resources/META-INF/resources/frontend/highlight-demo.css
@@ -1,8 +1,10 @@
+/* begin-block dashed */
.dashed {
border: 1px dashed black;
padding: 1ex;
margin: 1ex;
}
+/* end-block */
.dashed:hover {
background: var(--lumo-contrast-10pct);
diff --git a/base/src/test/resources/com/flowingcode/vaadin/addons/demo/it/CssFragment.css b/base/src/test/resources/com/flowingcode/vaadin/addons/demo/it/CssFragment.css
new file mode 100644
index 0000000..c056b33
--- /dev/null
+++ b/base/src/test/resources/com/flowingcode/vaadin/addons/demo/it/CssFragment.css
@@ -0,0 +1,9 @@
+/* begin-block fragment */
+.foo {
+ color: red;
+}
+/* end-block */
+
+.bar {
+ color: blue;
+}
diff --git a/base/src/test/resources/com/flowingcode/vaadin/addons/demo/it/CssFragment.txt b/base/src/test/resources/com/flowingcode/vaadin/addons/demo/it/CssFragment.txt
new file mode 100644
index 0000000..24184ab
--- /dev/null
+++ b/base/src/test/resources/com/flowingcode/vaadin/addons/demo/it/CssFragment.txt
@@ -0,0 +1,7 @@
+.foo {
+ color: red;
+}
+
+.bar {
+ color: blue;
+}
diff --git a/base/src/test/resources/com/flowingcode/vaadin/addons/demo/it/ShowSourceOverride.java b/base/src/test/resources/com/flowingcode/vaadin/addons/demo/it/ShowSourceOverride.java
new file mode 100644
index 0000000..478c2a3
--- /dev/null
+++ b/base/src/test/resources/com/flowingcode/vaadin/addons/demo/it/ShowSourceOverride.java
@@ -0,0 +1,7 @@
+class MyClass {
+
+ SourceCodeViewer.highlight(null); // show-source
+ SourceCodeViewer.highlightOnHover(div, "first"); // show-source
+ SourceCodeViewer.highlightOnClick(div, "second");
+
+}
diff --git a/base/src/test/resources/com/flowingcode/vaadin/addons/demo/it/ShowSourceOverride.txt b/base/src/test/resources/com/flowingcode/vaadin/addons/demo/it/ShowSourceOverride.txt
new file mode 100644
index 0000000..6e1ad6e
--- /dev/null
+++ b/base/src/test/resources/com/flowingcode/vaadin/addons/demo/it/ShowSourceOverride.txt
@@ -0,0 +1,6 @@
+class MyClass {
+
+ SourceCodeViewer.highlight(null);
+ SourceCodeViewer.highlightOnHover(div, "first");
+
+}
diff --git a/pom.xml b/pom.xml
index 9ecf419..fc59220 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
com.flowingcode.vaadin.addons.demo
commons-demo-aggregator
- 5.4.1-SNAPSHOT
+ 5.5.0-SNAPSHOT
pom
Commons Demo Aggregator
diff --git a/processor/pom.xml b/processor/pom.xml
index e7a6fcd..771c49c 100644
--- a/processor/pom.xml
+++ b/processor/pom.xml
@@ -5,7 +5,7 @@
com.flowingcode.vaadin.addons.demo
commons-demo-processor
- 5.4.1-SNAPSHOT
+ 5.5.0-SNAPSHOT
Commons Demo Processor
Annotation processor for Commons Demo: copies @DemoSource-referenced files into the class output