You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by lo...@apache.org on 2020/10/23 18:39:28 UTC
[myfaces-tobago] 02/13: TOBAGO-1633: Use TypeScript instead of
JavaScript. Simplify Renderers
This is an automated email from the ASF dual-hosted git repository.
lofwyr pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/myfaces-tobago.git
commit b1fe246fdc1698c97dfbc4a79ce9cfab295c4f56
Author: Udo Schnurpfeil <ud...@irian.eu>
AuthorDate: Thu Oct 22 12:26:25 2020 +0200
TOBAGO-1633: Use TypeScript instead of JavaScript.
Simplify Renderers
---
.../myfaces/tobago/component/RendererTypes.java | 2 -
.../apache/myfaces/tobago/config/TobagoConfig.java | 17 ++++-
.../renderkit/renderer/CommandRendererBase.java | 14 +++-
.../renderer/LinkInsideLinksRenderer.java | 67 ------------------
.../internal/renderkit/renderer/LinksRenderer.java | 17 ++---
.../internal/config/AbstractTobagoTestBase.java | 13 +++-
.../renderkit/renderer/InRendererUnitTest.java | 39 +----------
.../renderkit/renderer/LinkRendererUnitTest.java | 79 ++++++++++++++++++++++
.../renderkit/renderer/RendererTestBase.java | 63 +++++++++++++++++
.../renderer/link/link-inside-links-sub.html | 32 +++++++++
.../resources/renderer/link/link-inside-links.html | 26 +++++++
.../src/test/resources/renderer/link/link.html | 20 ++++++
12 files changed, 266 insertions(+), 123 deletions(-)
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/component/RendererTypes.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/component/RendererTypes.java
index b4cf843..f97e451 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/component/RendererTypes.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/component/RendererTypes.java
@@ -51,7 +51,6 @@ public enum RendererTypes {
Image,
Link,
LinkInsideCommand,
- LinkInsideLinks,
Links,
Label,
Messages,
@@ -136,7 +135,6 @@ public enum RendererTypes {
public static final String IMAGE = "Image";
public static final String LINK = "Link";
public static final String LINK_INSIDE_COMMAND = "LinkInsideCommand";
- public static final String LINK_INSIDE_LINKS = "LinkInsideLinks";
public static final String LINKS = "Links";
public static final String LABEL = "Label";
public static final String MESSAGES = "Messages";
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/config/TobagoConfig.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/config/TobagoConfig.java
index 4374d13..e7d0594 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/config/TobagoConfig.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/config/TobagoConfig.java
@@ -23,6 +23,8 @@ import org.apache.myfaces.tobago.context.Theme;
import org.apache.myfaces.tobago.internal.config.ContentSecurityPolicy;
import org.apache.myfaces.tobago.internal.config.SecurityAnnotation;
import org.apache.myfaces.tobago.sanitizer.Sanitizer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import javax.enterprise.inject.spi.CDI;
import javax.faces.context.FacesContext;
@@ -32,6 +34,8 @@ import java.util.Map;
public abstract class TobagoConfig {
+ private static final Logger LOG = LoggerFactory.getLogger(TobagoConfig.class);
+
/**
* @deprecated Since 5.0.0. Please use CDI.
*/
@@ -43,7 +47,18 @@ public abstract class TobagoConfig {
*/
@Deprecated
public static TobagoConfig getInstance(final FacesContext facesContext) {
- return CDI.current().select(TobagoConfig.class).get();
+ TobagoConfig tobagoConfig = null;
+ try {
+ tobagoConfig = CDI.current().select(TobagoConfig.class).get();
+ } catch (Exception e) {
+ LOG.warn("No CDI!");
+ }
+ if (tobagoConfig != null) {
+ return tobagoConfig;
+ } else {
+ // XXX not nice: this happens while unit tests and whenever???
+ return (TobagoConfig) facesContext.getExternalContext().getApplicationMap().get(TOBAGO_CONFIG);
+ }
}
/**
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/CommandRendererBase.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/CommandRendererBase.java
index 7b69c2b..38c5f4b 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/CommandRendererBase.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/CommandRendererBase.java
@@ -120,7 +120,8 @@ public abstract class CommandRendererBase<T extends AbstractUICommand> extends D
parentOfCommands ? null : getOuterCssItems(facesContext, component),
getCssItems(facesContext, component),
parentOfCommands && !dropdownSubmenu ? BootstrapClass.DROPDOWN_TOGGLE : null,
- component.getCustomClass());
+ component.getCustomClass(),
+ isInside(facesContext, HtmlElements.TOBAGO_LINKS) ? BootstrapClass.NAV_LINK : null);
final boolean defaultCommand = ComponentUtils.getBooleanAttribute(component, Attributes.defaultCommand);
if (defaultCommand) {
@@ -228,6 +229,7 @@ public abstract class CommandRendererBase<T extends AbstractUICommand> extends D
}
protected void encodeBeginOuter(final FacesContext facesContext, final T command) throws IOException {
+
final String clientId = command.getClientId(facesContext);
final boolean parentOfCommands = command.isParentOfCommands();
final boolean dropdownSubmenu = this instanceof LinkInsideCommandRenderer;
@@ -239,8 +241,16 @@ public abstract class CommandRendererBase<T extends AbstractUICommand> extends D
writer.startElement(HtmlElements.TOBAGO_DROPDOWN);
writer.writeIdAttribute(clientId);
+ final CssItem first;
+ if (childOfButtonGroup) {
+ first = null;
+ } else if (dropdownSubmenu) {
+ first = TobagoClass.DROPDOWN__SUBMENU;
+ } else {
+ first = BootstrapClass.DROPDOWN;
+ }
writer.writeClassAttribute(
- childOfButtonGroup ? null : dropdownSubmenu ? TobagoClass.DROPDOWN__SUBMENU : BootstrapClass.DROPDOWN,
+ first,
getOuterCssItems(facesContext, command));
}
}
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/LinkInsideLinksRenderer.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/LinkInsideLinksRenderer.java
deleted file mode 100644
index f33cc73..0000000
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/LinkInsideLinksRenderer.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * 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.myfaces.tobago.internal.renderkit.renderer;
-
-import org.apache.myfaces.tobago.internal.component.AbstractUILink;
-import org.apache.myfaces.tobago.renderkit.css.BootstrapClass;
-import org.apache.myfaces.tobago.renderkit.css.CssItem;
-import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
-import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
-
-import javax.faces.context.FacesContext;
-import java.io.IOException;
-
-public class LinkInsideLinksRenderer<T extends AbstractUILink> extends LinkRenderer<T> {
-
- @Override
- protected void encodeBeginOuter(final FacesContext facesContext, final T command) throws IOException {
- final String clientId = command.getClientId(facesContext);
- final boolean parentOfCommands = command.isParentOfCommands();
-
- final TobagoResponseWriter writer = getResponseWriter(facesContext);
-
- writer.startElement(HtmlElements.LI);
- if (parentOfCommands) {
- writer.startElement(HtmlElements.TOBAGO_DROPDOWN);
- writer.writeIdAttribute(clientId);
- }
-
- writer.writeClassAttribute(
- BootstrapClass.NAV_ITEM,
- parentOfCommands ? BootstrapClass.DROPDOWN : null);
- }
-
- @Override
- protected void encodeEndOuter(final FacesContext facesContext, final T command) throws IOException {
- final boolean parentOfCommands = command.isParentOfCommands();
-
- final TobagoResponseWriter writer = getResponseWriter(facesContext);
-
- if (parentOfCommands) {
- writer.endElement(HtmlElements.TOBAGO_DROPDOWN);
- }
- writer.endElement(HtmlElements.LI);
- }
-
- @Override
- protected CssItem[] getCssItems(final FacesContext facesContext, final T command) {
- return new CssItem[]{BootstrapClass.NAV_LINK};
- }
-}
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/LinksRenderer.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/LinksRenderer.java
index 2f775fd..bb0423f 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/LinksRenderer.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/LinksRenderer.java
@@ -19,8 +19,6 @@
package org.apache.myfaces.tobago.internal.renderkit.renderer;
-import org.apache.myfaces.tobago.component.RendererTypes;
-import org.apache.myfaces.tobago.internal.component.AbstractUILink;
import org.apache.myfaces.tobago.internal.component.AbstractUILinks;
import org.apache.myfaces.tobago.layout.Orientation;
import org.apache.myfaces.tobago.renderkit.RendererBase;
@@ -61,19 +59,16 @@ public class LinksRenderer<T extends AbstractUILinks> extends RendererBase<T> {
public void encodeChildrenInternal(final FacesContext facesContext, final T component) throws IOException {
final TobagoResponseWriter writer = getResponseWriter(facesContext);
+ insideBegin(facesContext, HtmlElements.TOBAGO_LINKS);
for (final UIComponent child : component.getChildren()) {
if (child.isRendered()) {
- if (child instanceof AbstractUILink) {
- child.setRendererType(RendererTypes.LinkInsideLinks.name());
- child.encodeAll(facesContext);
- } else {
- writer.startElement(HtmlElements.LI);
- writer.writeClassAttribute(BootstrapClass.NAV_ITEM);
- child.encodeAll(facesContext);
- writer.endElement(HtmlElements.LI);
- }
+ writer.startElement(HtmlElements.LI);
+ writer.writeClassAttribute(BootstrapClass.NAV_ITEM);
+ child.encodeAll(facesContext);
+ writer.endElement(HtmlElements.LI);
}
}
+ insideEnd(facesContext, HtmlElements.TOBAGO_LINKS);
}
@Override
diff --git a/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/config/AbstractTobagoTestBase.java b/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/config/AbstractTobagoTestBase.java
index ea63aa2..fbb0d5f 100644
--- a/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/config/AbstractTobagoTestBase.java
+++ b/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/config/AbstractTobagoTestBase.java
@@ -26,20 +26,23 @@ import org.apache.myfaces.test.mock.MockHttpServletRequest;
import org.apache.myfaces.tobago.component.RendererTypes;
import org.apache.myfaces.tobago.component.Tags;
import org.apache.myfaces.tobago.component.UIButton;
+import org.apache.myfaces.tobago.component.UIButtons;
import org.apache.myfaces.tobago.component.UIGridLayout;
import org.apache.myfaces.tobago.component.UIIn;
import org.apache.myfaces.tobago.component.UILink;
+import org.apache.myfaces.tobago.component.UILinks;
import org.apache.myfaces.tobago.component.UIOut;
import org.apache.myfaces.tobago.component.UIPanel;
import org.apache.myfaces.tobago.component.UIPopup;
import org.apache.myfaces.tobago.component.UISegmentLayout;
import org.apache.myfaces.tobago.component.UIStyle;
-import org.apache.myfaces.tobago.config.TobagoConfig;
import org.apache.myfaces.tobago.context.TobagoContext;
import org.apache.myfaces.tobago.internal.renderkit.renderer.ButtonRenderer;
+import org.apache.myfaces.tobago.internal.renderkit.renderer.ButtonsRenderer;
import org.apache.myfaces.tobago.internal.renderkit.renderer.GridLayoutRenderer;
import org.apache.myfaces.tobago.internal.renderkit.renderer.InRenderer;
import org.apache.myfaces.tobago.internal.renderkit.renderer.LinkRenderer;
+import org.apache.myfaces.tobago.internal.renderkit.renderer.LinksRenderer;
import org.apache.myfaces.tobago.internal.renderkit.renderer.OutRenderer;
import org.apache.myfaces.tobago.internal.renderkit.renderer.PanelRenderer;
import org.apache.myfaces.tobago.internal.renderkit.renderer.PopupRenderer;
@@ -55,6 +58,7 @@ import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
import java.util.Locale;
+import static org.apache.myfaces.tobago.config.TobagoConfig.TOBAGO_CONFIG;
import static org.apache.myfaces.tobago.util.ResourceUtils.TOBAGO_RESOURCE_BUNDLE;
/**
@@ -87,7 +91,8 @@ public abstract class AbstractTobagoTestBase extends AbstractJsfTestCase {
// Tobago specific extensions
final TobagoConfigImpl tobagoConfig = TobagoConfigMergingUnitTest.load("tobago-config-for-unit-tests.xml");
tobagoConfig.initDefaultValidatorInfo();
- servletContext.setAttribute(TobagoConfig.TOBAGO_CONFIG, tobagoConfig);
+ servletContext.setAttribute(TOBAGO_CONFIG, tobagoConfig);
+ facesContext.getExternalContext().getApplicationMap().put(TOBAGO_CONFIG, tobagoConfig);
final TobagoContext tobagoContext = new TobagoContext();
tobagoContext.setTheme(tobagoConfig.getDefaultTheme());
@@ -99,7 +104,9 @@ public abstract class AbstractTobagoTestBase extends AbstractJsfTestCase {
application.addComponent(Tags.out.componentType(), UIOut.class.getName());
application.addComponent(Tags.panel.componentType(), UIPanel.class.getName());
application.addComponent(Tags.link.componentType(), UILink.class.getName());
+ application.addComponent(Tags.links.componentType(), UILinks.class.getName());
application.addComponent(Tags.button.componentType(), UIButton.class.getName());
+ application.addComponent(Tags.buttons.componentType(), UIButtons.class.getName());
application.addComponent(Tags.popup.componentType(), UIPopup.class.getName());
application.addComponent(Tags.style.componentType(), UIStyle.class.getName());
application.addComponent(Tags.gridLayout.componentType(), UIGridLayout.class.getName());
@@ -110,7 +117,9 @@ public abstract class AbstractTobagoTestBase extends AbstractJsfTestCase {
renderKit.addRenderer(UIOut.COMPONENT_FAMILY, RendererTypes.OUT, new OutRenderer());
renderKit.addRenderer(UIPanel.COMPONENT_FAMILY, RendererTypes.PANEL, new PanelRenderer());
renderKit.addRenderer(UILink.COMPONENT_FAMILY, RendererTypes.LINK, new LinkRenderer());
+ renderKit.addRenderer(UILinks.COMPONENT_FAMILY, RendererTypes.LINKS, new LinksRenderer());
renderKit.addRenderer(UIButton.COMPONENT_FAMILY, RendererTypes.BUTTON, new ButtonRenderer());
+ renderKit.addRenderer(UIButtons.COMPONENT_FAMILY, RendererTypes.BUTTONS, new ButtonsRenderer());
renderKit.addRenderer(UIPopup.COMPONENT_FAMILY, RendererTypes.POPUP, new PopupRenderer());
renderKit.addRenderer(UIStyle.COMPONENT_FAMILY, RendererTypes.STYLE, new StyleRenderer());
renderKit.addRenderer(UIGridLayout.COMPONENT_FAMILY, RendererTypes.GRID_LAYOUT, new GridLayoutRenderer());
diff --git a/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/renderkit/renderer/InRendererUnitTest.java b/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/renderkit/renderer/InRendererUnitTest.java
index 5b999b6..f78cf7f 100644
--- a/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/renderkit/renderer/InRendererUnitTest.java
+++ b/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/renderkit/renderer/InRendererUnitTest.java
@@ -24,20 +24,14 @@ import org.apache.myfaces.tobago.component.RendererTypes;
import org.apache.myfaces.tobago.component.Tags;
import org.apache.myfaces.tobago.component.UIIn;
import org.apache.myfaces.tobago.component.UISegmentLayout;
-import org.apache.myfaces.tobago.internal.config.AbstractTobagoTestBase;
import org.apache.myfaces.tobago.layout.SegmentMeasureList;
import org.apache.myfaces.tobago.util.ComponentUtils;
import org.junit.Assert;
import org.junit.jupiter.api.Test;
-import java.io.BufferedReader;
-import java.io.FileNotFoundException;
import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.util.stream.Collectors;
-public class InRendererUnitTest extends AbstractTobagoTestBase {
+public class InRendererUnitTest extends RendererTestBase {
@Test
public void simple() throws IOException {
@@ -204,35 +198,4 @@ public class InRendererUnitTest extends AbstractTobagoTestBase {
Assert.assertEquals(loadHtml("renderer/in/label-none.html"), formattedResult());
}
-
- private String formattedResult() throws IOException {
- return format1To2Indent(getLastWritten());
- }
-
- private String loadHtml(final String fileName) throws IOException {
- final ClassLoader classLoader = ClassLoader.getSystemClassLoader();
- try (InputStream is = classLoader.getResourceAsStream(fileName)) {
- if (is == null) {
- throw new FileNotFoundException(fileName);
- }
- try (final InputStreamReader isr = new InputStreamReader(is);
- final BufferedReader reader = new BufferedReader(isr)) {
- return reader.lines().collect(Collectors.joining(System.lineSeparator()))
- .replaceAll("<!--[^>]*-->", "")
- .replaceAll("^\n\n", "");
- }
- }
- }
-
- private String format1To2Indent(final String xml) {
- return xml.replaceAll("^\n", "")
- .replaceAll("\n <", "\n\t<")
- .replaceAll("\n <", "\n\t\t<")
- .replaceAll("\n <", "\n\t\t\t<")
- .replaceAll("\n <", "\n\t\t\t\t<")
- .replaceAll("\n <", "\n\t\t\t\t\t<")
- .replaceAll("\n <", "\n\t\t\t\t\t\t<")
- .replaceAll("\n <", "\n\t\t\t\t\t\t\t<")
- .replaceAll("\t", " ");
- }
}
diff --git a/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/renderkit/renderer/LinkRendererUnitTest.java b/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/renderkit/renderer/LinkRendererUnitTest.java
new file mode 100644
index 0000000..d4df468
--- /dev/null
+++ b/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/renderkit/renderer/LinkRendererUnitTest.java
@@ -0,0 +1,79 @@
+/*
+ * 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.myfaces.tobago.internal.renderkit.renderer;
+
+import org.apache.myfaces.tobago.component.RendererTypes;
+import org.apache.myfaces.tobago.component.Tags;
+import org.apache.myfaces.tobago.component.UILink;
+import org.apache.myfaces.tobago.component.UILinks;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+import org.junit.Assert;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+
+public class LinkRendererUnitTest extends RendererTestBase {
+
+ @Test
+ public void link() throws IOException {
+ final UILink c = (UILink) ComponentUtils.createComponent(
+ facesContext, Tags.link.componentType(), RendererTypes.Link, "id");
+ c.setLabel("label");
+ c.setLink("https://www.apache.org/");
+ c.encodeAll(facesContext);
+
+ Assert.assertEquals(loadHtml("renderer/link/link.html"), formattedResult());
+ }
+
+ @Test
+ public void linkInsideLinks() throws IOException {
+ final UILinks l = (UILinks) ComponentUtils.createComponent(
+ facesContext, Tags.links.componentType(), RendererTypes.Links, "list");
+ final UILink c = (UILink) ComponentUtils.createComponent(
+ facesContext, Tags.link.componentType(), RendererTypes.Link, "id");
+ c.setLabel("apache");
+ c.setLink("https://www.apache.org/");
+ l.getChildren().add(c);
+ l.encodeAll(facesContext);
+
+ Assert.assertEquals(loadHtml("renderer/link/link-inside-links.html"), formattedResult());
+ }
+
+ @Test
+ public void linkInsideLinksSub() throws IOException {
+ final UILinks l = (UILinks) ComponentUtils.createComponent(
+ facesContext, Tags.links.componentType(), RendererTypes.Links, "list");
+ final UILink c = (UILink) ComponentUtils.createComponent(
+ facesContext, Tags.link.componentType(), RendererTypes.Link, "id");
+ c.setLabel("apache");
+
+ final UILink s = (UILink) ComponentUtils.createComponent(
+ facesContext, Tags.link.componentType(), RendererTypes.Link, "sub");
+ s.setLabel("sub");
+ s.setLink("https://www.apache.org/");
+ c.getChildren().add(s);
+
+ l.getChildren().add(c);
+ l.encodeAll(facesContext);
+
+ Assert.assertEquals(loadHtml("renderer/link/link-inside-links-sub.html"), formattedResult());
+ }
+
+}
diff --git a/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/renderkit/renderer/RendererTestBase.java b/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/renderkit/renderer/RendererTestBase.java
new file mode 100644
index 0000000..c1c72ce
--- /dev/null
+++ b/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/renderkit/renderer/RendererTestBase.java
@@ -0,0 +1,63 @@
+/*
+ * 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.myfaces.tobago.internal.renderkit.renderer;
+
+import org.apache.myfaces.tobago.internal.config.AbstractTobagoTestBase;
+
+import java.io.BufferedReader;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.stream.Collectors;
+
+public abstract class RendererTestBase extends AbstractTobagoTestBase {
+
+ protected String formattedResult() throws IOException {
+ return format1To2Indent(getLastWritten());
+ }
+
+ protected String loadHtml(final String fileName) throws IOException {
+ final ClassLoader classLoader = ClassLoader.getSystemClassLoader();
+ try (InputStream is = classLoader.getResourceAsStream(fileName)) {
+ if (is == null) {
+ throw new FileNotFoundException(fileName);
+ }
+ try (final InputStreamReader isr = new InputStreamReader(is);
+ final BufferedReader reader = new BufferedReader(isr)) {
+ return reader.lines().collect(Collectors.joining(System.lineSeparator()))
+ .replaceAll("<!--[^>]*-->", "")
+ .replaceAll("^\n\n", "");
+ }
+ }
+ }
+
+ protected String format1To2Indent(final String xml) {
+ return xml.replaceAll("^\n", "")
+ .replaceAll("\n <", "\n\t<")
+ .replaceAll("\n <", "\n\t\t<")
+ .replaceAll("\n <", "\n\t\t\t<")
+ .replaceAll("\n <", "\n\t\t\t\t<")
+ .replaceAll("\n <", "\n\t\t\t\t\t<")
+ .replaceAll("\n <", "\n\t\t\t\t\t\t<")
+ .replaceAll("\n <", "\n\t\t\t\t\t\t\t<")
+ .replaceAll("\t", " ");
+ }
+}
diff --git a/tobago-core/src/test/resources/renderer/link/link-inside-links-sub.html b/tobago-core/src/test/resources/renderer/link/link-inside-links-sub.html
new file mode 100644
index 0000000..fc95c8e
--- /dev/null
+++ b/tobago-core/src/test/resources/renderer/link/link-inside-links-sub.html
@@ -0,0 +1,32 @@
+<!--
+ * 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.
+-->
+<!--
+CSS class nav-item has moved from "tobago-dropdown" to "li"
+-->
+<tobago-links id='list'>
+ <ul class='nav'>
+ <li class='nav-item'>
+ <tobago-dropdown id='id' class='dropdown'>
+ <button type='button' id='id::command' name='id' data-toggle='dropdown' class='tobago-link dropdown-toggle nav-link'>
+ <tobago-behavior event='click' decoupled='decoupled'>
+ </tobago-behavior><span>apache</span></button>
+ <div class='dropdown-menu' aria-labelledby='id::command' name='id'>
+ </div>
+ </tobago-dropdown>
+ </li>
+ </ul>
+</tobago-links>
\ No newline at end of file
diff --git a/tobago-core/src/test/resources/renderer/link/link-inside-links.html b/tobago-core/src/test/resources/renderer/link/link-inside-links.html
new file mode 100644
index 0000000..c3fca1d
--- /dev/null
+++ b/tobago-core/src/test/resources/renderer/link/link-inside-links.html
@@ -0,0 +1,26 @@
+<!--
+ * 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.
+-->
+
+<tobago-links id='list'>
+ <ul class='nav'>
+ <li class='nav-item'>
+ <a id='id' name='id' href='https://www.apache.org/' class='tobago-link nav-link'>
+ <tobago-behavior event='click' omit='omit' decoupled='decoupled'>
+ </tobago-behavior><span>apache</span></a>
+ </li>
+ </ul>
+</tobago-links>
\ No newline at end of file
diff --git a/tobago-core/src/test/resources/renderer/link/link.html b/tobago-core/src/test/resources/renderer/link/link.html
new file mode 100644
index 0000000..a327675
--- /dev/null
+++ b/tobago-core/src/test/resources/renderer/link/link.html
@@ -0,0 +1,20 @@
+<!--
+ * 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.
+-->
+
+<a id='id' name='id' href='https://www.apache.org/' class='tobago-link'>
+ <tobago-behavior event='click' omit='omit' decoupled='decoupled'>
+ </tobago-behavior><span>label</span></a>
\ No newline at end of file