Revision: 609
Author: allain.lalonde
Date: Tue Jul 28 21:35:50 2009
Log: Made PHtml not use regular expressions for parsing HTML3.2 since it
really couldn't handle malformed HTML at all. At least now there's a
passing attempt.
http://code.google.com/p/piccolo2d/source/detail?r=609
Added:
/piccolo2d.java/branches/phtml/core/src/test/java/edu/umd/cs/piccolo/nodes/PHtmlTest.java
Modified:
/piccolo2d.java/branches/phtml/core/src/main/java/edu/umd/cs/piccolo/nodes/PHtml.java
=======================================
--- /dev/null
+++
/piccolo2d.java/branches/phtml/core/src/test/java/edu/umd/cs/piccolo/nodes/PHtmlTest.java
Tue Jul 28 21:35:50 2009
@@ -0,0 +1,52 @@
+package edu.umd.cs.piccolo.nodes;
+
+import java.awt.geom.Point2D;
+
+import junit.framework.TestCase;
+import edu.umd.cs.piccolo.util.PBounds;
+
+public class PHtmlTest extends TestCase {
+
+ public void testGetClickedAddressReturnsSingleQuotedAddress() {
+ PHtml html = new PHtml("<a
href='http://www.testing.com'>testing</a>");
+ html.setBounds(new PBounds(0, 0, 100, 100));
+ assertEquals("http://www.testing.com", html.getClickedAddress(new
Point2D.Double(5,5)));
+ }
+
+ public void testGetClickedAddressReturnsDoubleQuotedAddress() {
+ PHtml html = new PHtml("<a
href=\"http://www.testing.com\">testing</a>");
+ html.setBounds(new PBounds(0, 0, 100, 100));
+ assertEquals("http://www.testing.com", html.getClickedAddress(new
Point2D.Double(5,5)));
+ }
+
+ public void testBracketsAreValidInHrefs() {
+ PHtml html = new PHtml("<a href='a>b'>testing</a>");
+ html.setBounds(new PBounds(0, 0, 100, 100));
+ assertEquals("a>b", html.getClickedAddress(new
Point2D.Double(5,5)));
+ }
+
+ public void testGetClickedAddressReturnsNullWhenInvalid() {
+ PHtml html = new PHtml("<a ='a>b'>testing</a>");
+ html.setBounds(new PBounds(0, 0, 100, 100));
+ assertNull(html.getClickedAddress(new Point2D.Double(5,5)));
+ }
+
+ public void testGetClickedAddressReturnsHrefWhenMissingEndAnchorTag() {
+ PHtml html = new PHtml("<a href='testing.com'>testing");
+ html.setBounds(new PBounds(0, 0, 100, 100));
+ assertEquals("testing.com", html.getClickedAddress(new
Point2D.Double(5,5)));
+ }
+
+ public void testHandlesTricksyTitles() {
+ PHtml html = new PHtml("<a href=\"where to go\" title=\"this is
not the href='gotcha!' \">testing</a>");
+ html.setBounds(new PBounds(0, 0, 100, 100));
+ assertEquals("where to go", html.getClickedAddress(new
Point2D.Double(5,5)));
+ }
+
+ public void testHandlesHrefWithoutQuotes() {
+ PHtml html = new PHtml("<a href=testing.com>testing</a>");
+ html.setBounds(new PBounds(0, 0, 100, 100));
+ assertEquals("testing.com", html.getClickedAddress(new
Point2D.Double(5,5)));
+ }
+
+}
=======================================
---
/piccolo2d.java/branches/phtml/core/src/main/java/edu/umd/cs/piccolo/nodes/PHtml.java
Tue Jul 28 14:37:17 2009
+++
/piccolo2d.java/branches/phtml/core/src/main/java/edu/umd/cs/piccolo/nodes/PHtml.java
Tue Jul 28 21:35:50 2009
@@ -61,12 +61,6 @@
private static final long serialVersionUID = 1L;
- // FIXME: imagine <img alt="2>1" src="here comes the meat" />
- private static final Pattern tagPattern = Pattern.compile("</?[^>]+>");
- // FIXME: imagine <a href="where to go"
- // title="this is not the href='gotcha!' " />
- private static final Pattern linkPattern =
Pattern.compile("<a .*href=(\\\"([^\\\"]*)\\\"|\\\'([^\\\"]*)\\\')");
-
private static final Font DEFAULT_FONT = new JTextField().getFont();
private static final Color DEFAULT_HTML_COLOR = Color.BLACK;
@@ -253,32 +247,103 @@
public String getClickedAddress(final Point2D clickedPoint) {
int position = pointToModelIndex(clickedPoint);
- final Matcher tagMatcher = tagPattern.matcher(htmlLabel.getText());
+ String html = htmlLabel.getText();
String address = null;
- while (tagMatcher.find()) {
- if (position <= tagMatcher.start()) {
+ int currentPos = 0;
+ while (currentPos < html.length()) {
+ if (html.charAt(currentPos) != '<') {
+ currentPos++;
+ }
+ else if (position < currentPos) {
break;
}
- position += tagMatcher.end() - tagMatcher.start();
-
- final String tag = tagMatcher.group().toLowerCase();
- if ("</a>".equals(tag)) {
- address = null;
- }
- else {
- final Matcher linkMatcher = linkPattern.matcher(tag);
- if (linkMatcher.find()) {
- address = linkMatcher.group(2);
- if (address == null) {
- address = linkMatcher.group(3);
- }
+ else {
+ int tagStart = currentPos;
+ int tagEnd = findTagEnd(html, currentPos);
+
+ currentPos = tagEnd + 1;
+
+ String tag = html.substring(tagStart, tagEnd);
+
+ position += tag.length();
+
+ if ("</a>".equals(tag)) {
+ address = null;
+ }
+ else if (tag.startsWith("<a ")) {
+ address = extractHref(tag);
+ }
+ }
+ }
+
+ return address;
+ }
+
+ private String extractHref(String tag) {
+ int currentPos = 0;
+
+ String href = null;
+ int tagLength = tag.length();
+
+ while (currentPos < tag.length() - 1) {
+ currentPos++;
+ if (tag.charAt(currentPos) != '=') {
+ currentPos++;
+ }
+ else if (currentPos > 4 && "
href".equals(tag.substring(currentPos - 5, currentPos))) {
+ currentPos++;
+ if (tag.charAt(currentPos) == '\"') {
+ int startHref = currentPos + 1;
+ if (currentPos < tagLength) {
+ do {
+ ++currentPos;
+ } while (currentPos < tagLength &&
tag.charAt(currentPos) != '\"');
+ }
+ return tag.substring(startHref, currentPos);
+ }
+ else if (currentPos < tagLength && tag.charAt(currentPos)
== '\'') {
+ int startHref = currentPos + 1;
+ if (currentPos < tagLength) {
+ do {
+ ++currentPos;
+ } while (currentPos < tagLength &&
tag.charAt(currentPos) != '\'');
+ }
+ return tag.substring(startHref, currentPos);
+ }
+ else {
+ int startHref = currentPos;
+
+ if (currentPos < tagLength) {
+ do {
+ currentPos++;
+ } while (currentPos < tagLength &&
tag.charAt(currentPos) != ' '
+ && tag.charAt(currentPos) != '>');
+ }
+ return tag.substring(startHref, currentPos);
}
}
}
-
- return address;
+ return href;
+ }
+
+ private int findTagEnd(String html, final int startPos) {
+ int currentPos = startPos;
+
+ while (html.charAt(currentPos) != '>') {
+ if (html.charAt(currentPos) == '\"') {
+ while (html.charAt(++currentPos) != '\"')
+ ;
+ }
+ else if (html.charAt(currentPos) == '\'') {
+ while (html.charAt(++currentPos) != '\'')
+ ;
+ }
+ currentPos++;
+ }
+
+ return currentPos + 1;
}
private int pointToModelIndex(final Point2D clickedPoint) {
--~--~---------~--~----~------------~-------~--~----~
Piccolo2D Developers Group: http://groups.google.com/group/piccolo2d-dev?hl=en
-~----------~----~----~----~------~----~------~--~---