tapestry-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jkemn...@apache.org
Subject [1/2] git commit: TAP5-2266: extend support for HTML content inside parameter JavaDoc
Date Sat, 17 May 2014 12:14:36 GMT
Repository: tapestry-5
Updated Branches:
  refs/heads/master c44abfd6a -> fd3c9e6b7


TAP5-2266: extend support for HTML content inside parameter JavaDoc


Project: http://git-wip-us.apache.org/repos/asf/tapestry-5/repo
Commit: http://git-wip-us.apache.org/repos/asf/tapestry-5/commit/bb309644
Tree: http://git-wip-us.apache.org/repos/asf/tapestry-5/tree/bb309644
Diff: http://git-wip-us.apache.org/repos/asf/tapestry-5/diff/bb309644

Branch: refs/heads/master
Commit: bb3096442155f68a69cee0b709717c09287bdea9
Parents: c44abfd
Author: Jochen Kemnade <jkemnade@apache.org>
Authored: Sat May 17 13:57:30 2014 +0200
Committer: Jochen Kemnade <jkemnade@apache.org>
Committed: Sat May 17 14:05:30 2014 +0200

----------------------------------------------------------------------
 .../tapestry5/corelib/components/DevTool.java   |   2 +-
 tapestry-javadoc/build.gradle                   |   3 +
 .../tapestry5/javadoc/ParameterDescription.java |  55 ++++++--
 .../javadoc/ParameterDescriptionSpec.groovy     | 125 +++++++++++++++++++
 4 files changed, 172 insertions(+), 13 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/bb309644/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/DevTool.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/DevTool.java
b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/DevTool.java
index 320e1cd..0954e66 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/DevTool.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/DevTool.java
@@ -58,7 +58,7 @@ public class DevTool
 
     /**
      * If true, then the DevTool modifies its markup so as to work within a Bootstrap 3 NavBar.
This renders
-     * the component as an {@code <li>} (instead of a {@code <div>}), and removes
the "btn" CSS classes.
+     * the component as a {@code <li>} (instead of a {@code <div>}), and removes
the "btn" CSS classes.
      */
     @Parameter
     private boolean navbar;

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/bb309644/tapestry-javadoc/build.gradle
----------------------------------------------------------------------
diff --git a/tapestry-javadoc/build.gradle b/tapestry-javadoc/build.gradle
index 032114a..efc6f9d 100644
--- a/tapestry-javadoc/build.gradle
+++ b/tapestry-javadoc/build.gradle
@@ -4,6 +4,9 @@ dependencies {
   compile project(':tapestry-core')
   compile "commons-lang:commons-lang:2.6"
   compile files(getTools())
+  
+  testCompile "org.spockframework:spock-core:${versions.spock}"
+  
 }
 
 /** Returns the tools.jar/classes.jar of the Java runtime. */

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/bb309644/tapestry-javadoc/src/main/java/org/apache/tapestry5/javadoc/ParameterDescription.java
----------------------------------------------------------------------
diff --git a/tapestry-javadoc/src/main/java/org/apache/tapestry5/javadoc/ParameterDescription.java
b/tapestry-javadoc/src/main/java/org/apache/tapestry5/javadoc/ParameterDescription.java
index a60f8a7..ff8bc11 100644
--- a/tapestry-javadoc/src/main/java/org/apache/tapestry5/javadoc/ParameterDescription.java
+++ b/tapestry-javadoc/src/main/java/org/apache/tapestry5/javadoc/ParameterDescription.java
@@ -14,14 +14,18 @@
 
 package org.apache.tapestry5.javadoc;
 
-import com.sun.javadoc.FieldDoc;
-import com.sun.javadoc.SeeTag;
-import com.sun.javadoc.Tag;
-
 import java.io.IOException;
+import java.util.Locale;
+import java.util.Set;
+import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
 import org.apache.commons.lang.StringEscapeUtils;
+import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
+
+import com.sun.javadoc.FieldDoc;
+import com.sun.javadoc.SeeTag;
+import com.sun.javadoc.Tag;
 
 public class ParameterDescription
 {
@@ -45,10 +49,12 @@ public class ParameterDescription
 
     public final boolean deprecated;
 
-    private static final Pattern STRIPPER = Pattern.compile("(<.*?>|&.*?;)", Pattern.DOTALL);
+    private static final Pattern SPECIAL_CONTENT = Pattern.compile("(?:</?(\\p{Alpha}+)>)|(?:&\\p{Alpha}+;)");
+    private static final Set<String> PASS_THROUGH_TAGS = CollectionFactory.newSet("b",
"em", "i", "code", "strong");
 
-    public ParameterDescription(FieldDoc fieldDoc, String name, String type, String defaultValue,
String defaultPrefix,
-                                boolean required, boolean allowNull, boolean cache, String
since, boolean deprecated)
+
+    public ParameterDescription(final FieldDoc fieldDoc, final String name, final String
type, final String defaultValue, final String defaultPrefix,
+            final boolean required, final boolean allowNull, final boolean cache, final String
since, final boolean deprecated)
     {
         this.field = fieldDoc;
         this.name = name;
@@ -76,7 +82,7 @@ public class ParameterDescription
         {
             if (tag.name().equals("Text"))
             {
-                builder.append(tag.text());
+                appendContentSafe(builder, tag.text());
                 continue;
             }
 
@@ -87,17 +93,17 @@ public class ParameterDescription
                 String label = seeTag.label();
                 if (label != null && !label.equals(""))
                 {
-                    builder.append(label);
+                    builder.append(StringEscapeUtils.escapeHtml(label));
                     continue;
                 }
 
                 if (seeTag.referencedClassName() != null)
-                    builder.append(seeTag.referencedClassName());
+                    builder.append(StringEscapeUtils.escapeHtml(seeTag.referencedClassName()));
 
                 if (seeTag.referencedMemberName() != null)
                 {
                     builder.append("#");
-                    builder.append(seeTag.referencedMemberName());
+                    builder.append(StringEscapeUtils.escapeHtml(seeTag.referencedMemberName()));
                 }
             }
             else if (tag.name().equals("@code"))
@@ -114,6 +120,31 @@ public class ParameterDescription
 
         // Remove any simple open or close tags found in the text, as well as any XML entities.
 
-        return STRIPPER.matcher(text).replaceAll("").trim();
+        return text.trim();
+    }
+
+    private static void appendContentSafe(final StringBuilder sb, final String string){
+        Matcher m = SPECIAL_CONTENT.matcher(string);
+        int index = 0;
+        while (index < string.length()){
+            boolean match = m.find(index);
+            if (match){
+                if (index != m.start()){
+                    sb.append(StringEscapeUtils.escapeHtml(string.substring(index, m.start())));
+                }
+                String tagName = m.group(1);
+                if (tagName!= null){
+                    if(PASS_THROUGH_TAGS.contains(tagName.toLowerCase(Locale.US))){
+                        sb.append(m.group());
+                    }
+                }else{
+                    sb.append(m.group());
+                }
+                index = m.end();
+            }else{
+                sb.append(StringEscapeUtils.escapeHtml(string.substring(index)));
+                break;
+            }
+        }
     }
 }

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/bb309644/tapestry-javadoc/src/test/groovy/org/apache/tapestry5/javadoc/ParameterDescriptionSpec.groovy
----------------------------------------------------------------------
diff --git a/tapestry-javadoc/src/test/groovy/org/apache/tapestry5/javadoc/ParameterDescriptionSpec.groovy
b/tapestry-javadoc/src/test/groovy/org/apache/tapestry5/javadoc/ParameterDescriptionSpec.groovy
new file mode 100644
index 0000000..008d1b1
--- /dev/null
+++ b/tapestry-javadoc/src/test/groovy/org/apache/tapestry5/javadoc/ParameterDescriptionSpec.groovy
@@ -0,0 +1,125 @@
+package org.apache.tapestry5.javadoc
+
+import spock.lang.Specification
+
+import com.sun.javadoc.FieldDoc
+import com.sun.tools.doclets.internal.toolkit.util.TextTag
+import com.sun.tools.javadoc.TagImpl
+
+
+class ParameterDescriptionSpec extends Specification {
+
+	def "Parameter description without embedded tags is passed through"(){
+		setup:
+		FieldDoc fieldDoc = Mock()
+		def inlineTags = [
+			new TextTag(null, "Plain text")
+		]
+		ParameterDescription parameterDescription = new ParameterDescription(fieldDoc, "parameter",
"String", "value", "literal", false, true, false, "1", false)
+		when:
+		def extracted = parameterDescription.extractDescription()
+		then:
+		1 * fieldDoc.inlineTags() >> inlineTags
+		extracted == "Plain text"
+	}
+
+	def "Embedded code tags are turned into HTML <code> elements"(){
+		setup:
+		FieldDoc fieldDoc = Mock()
+		def inlineTags = [
+			new TagImpl(null, "@code", "blah")
+		]
+		ParameterDescription parameterDescription = new ParameterDescription(fieldDoc, "parameter",
"String", "value", "literal", false, true, false, "1", false)
+		when:
+		def extracted = parameterDescription.extractDescription()
+		then:
+		1 * fieldDoc.inlineTags() >> inlineTags
+		extracted == "<code>blah</code>"
+	}
+
+	// TAP5-2266
+	def "HTML in embedded code tags is escaped"(){
+		setup:
+		FieldDoc fieldDoc = Mock()
+		def inlineTags = [
+			new TextTag(null, "This renders the component as a "),
+			new TagImpl(null, "@code", "<li>"),
+			new TextTag(null, " (instead of a "),
+			new TagImpl(null, "@code", "<div>"),
+			new TextTag(null, ")")
+		]
+		ParameterDescription parameterDescription = new ParameterDescription(fieldDoc, "parameter",
"String", "value", "literal", false, true, false, "1", false)
+		when:
+		def extracted = parameterDescription.extractDescription()
+		then:
+		1 * fieldDoc.inlineTags() >> inlineTags
+		extracted == "This renders the component as a <code>&lt;li&gt;</code>
(instead of a <code>&lt;div&gt;</code>)"
+	}
+
+
+	def "Characters with special meaning are escaped"(){
+		setup:
+		FieldDoc fieldDoc = Mock()
+		def inlineTags = [
+			new TextTag(null, "Javadoc with < character")
+		]
+		ParameterDescription parameterDescription = new ParameterDescription(fieldDoc, "parameter",
"String", "value", "literal", false, true, false, "1", false)
+		when:
+		def extracted = parameterDescription.extractDescription()
+		then:
+		1 * fieldDoc.inlineTags() >> inlineTags
+		extracted == "Javadoc with &lt; character"
+	}
+
+	def "Entities in Javadoc are left alone"(){
+		setup:
+		FieldDoc fieldDoc = Mock()
+		def inlineTags = [
+			new TextTag(null, "Text &amp; entity")
+		]
+		ParameterDescription parameterDescription = new ParameterDescription(fieldDoc, "parameter",
"String", "value", "literal", false, true, false, "1", false)
+		when:
+		def extracted = parameterDescription.extractDescription()
+		then:
+		1 * fieldDoc.inlineTags() >> inlineTags
+		extracted == "Text &amp; entity"
+	}
+
+	def "Un-safe tags in Javadoc are removed"(){
+		setup:
+		FieldDoc fieldDoc = Mock()
+		def inlineTags = [
+			new TextTag(null, "We don't <br>want new lines or</td> table stuff")
+		]
+		ParameterDescription parameterDescription = new ParameterDescription(fieldDoc, "parameter",
"String", "value", "literal", false, true, false, "1", false)
+		when:
+		def extracted = parameterDescription.extractDescription()
+		then:
+		1 * fieldDoc.inlineTags() >> inlineTags
+		extracted == "We don't want new lines or table stuff"
+	}
+
+	def "#src in Javadoc becomes #target in HTML"(){
+		setup:
+		FieldDoc fieldDoc = Mock()
+		def inlineTags = [
+			new TextTag(null, src)
+		]
+		ParameterDescription parameterDescription = new ParameterDescription(fieldDoc, "parameter",
"String", "value", "literal", false, true, false, "1", false)
+		when:
+		def extracted = parameterDescription.extractDescription()
+		then:
+		1 * fieldDoc.inlineTags() >> inlineTags
+		extracted == target
+		where:
+		src     | target
+		"&"     | "&amp;"
+		"&amp;" | "&amp;"
+		"<"     | "&lt;"
+		"<b>"   | "<b>"
+
+	}
+
+
+
+}


Mime
View raw message