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. ![image](https://github.com/FlowingCode/CommonsDemo/assets/11554739/083cf7ec-0f36-4db8-ab61-6c24650f4f13) @@ -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 */ +``` + ![image](https://github.com/FlowingCode/CommonsDemo/assets/11554739/02063272-029f-4b4b-bd6f-821f2f8a0158) 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