Updated Branches: refs/heads/master 06f1d79f2 -> 4f31d4d71
Alert support in markdown, expanded examples Project: http://git-wip-us.apache.org/repos/asf/wicket/repo Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/4f31d4d7 Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/4f31d4d7 Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/4f31d4d7 Branch: refs/heads/master Commit: 4f31d4d715097b3e55acac6d084486a4a9e1ac08 Parents: 06f1d79 Author: Martijn Dashorst <[email protected]> Authored: Tue Oct 9 11:00:10 2012 +0200 Committer: Martijn Dashorst <[email protected]> Committed: Tue Oct 9 11:00:10 2012 +0200 ---------------------------------------------------------------------- .../wicket/examples/base/markdown/Markdown.java | 117 +++++++++++ .../examples/base/markdown/MarkdownLabel.java | 61 +------ .../apache/wicket/examples/components/Labels.md | 2 +- .../org/apache/wicket/examples/components/Links.md | 149 ++++++++++++++- .../wicket/examples/components/Pagination.md | 88 +--------- .../examples/base/markdown/MarkdownTest.java | 63 ++++++ .../apache/wicket/examples/base/markdown/alert3.md | 11 + .../wicket/examples/base/markdown/expected3.html | 13 ++ 8 files changed, 354 insertions(+), 150 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/wicket/blob/4f31d4d7/wicket-experimental/wicket-examples-parent/wicket-examples-jar/src/main/java/org/apache/wicket/examples/base/markdown/Markdown.java ---------------------------------------------------------------------- diff --git a/wicket-experimental/wicket-examples-parent/wicket-examples-jar/src/main/java/org/apache/wicket/examples/base/markdown/Markdown.java b/wicket-experimental/wicket-examples-parent/wicket-examples-jar/src/main/java/org/apache/wicket/examples/base/markdown/Markdown.java new file mode 100644 index 0000000..5900767 --- /dev/null +++ b/wicket-experimental/wicket-examples-parent/wicket-examples-jar/src/main/java/org/apache/wicket/examples/base/markdown/Markdown.java @@ -0,0 +1,117 @@ +/* + * 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.wicket.examples.base.markdown; + +import java.util.ArrayList; +import java.util.Iterator; + +import org.apache.wicket.util.string.Strings; + +import com.google.common.base.Splitter; +import com.petebevin.markdown.MarkdownProcessor; + +/** + */ +public class Markdown +{ + /** + * @param markdown + * @return + */ + public static String markdownToHtml(String markdown) + { + MarkdownProcessor processor = new MarkdownProcessor(); + String text = processor.markdown(markdown); + + text = processLiquidTags(text); + return text; + } + + private static String processLiquidTags(String text) + { + String markup; + StringBuilder sb = new StringBuilder(); + + int previousStart = 0; + int start = text.indexOf("{% "); + while (start > 0) + { + int end = text.indexOf("{% end", start); + end = text.indexOf("%}", end + 5) + 2; + sb.append(text.substring(previousStart, start)); + + String block = text.substring(start, end); + + if (block.startsWith("{% highlight")) + { + sb.append(handleCodeBlock(block)); + } + if (block.startsWith("{% alert")) + { + sb.append(handleAlert(block)); + } + sb.append("\n"); + previousStart = end; + start = text.indexOf("{% ", end); + } + if (previousStart < text.length()) + sb.append(text.substring(previousStart)); + + markup = sb.toString(); + return markup; + } + + private static String handleCodeBlock(String codeblock) + { + codeblock = codeblock.replaceAll("\\{\\% highlight (.+) \\%\\}", + "<pre class=\"prettyprint linenums\" lang=\"$1\">"); + codeblock = codeblock.replaceAll("\\{\\% endhighlight \\%\\}", "</pre>"); + + int start = codeblock.indexOf(">") + 1; + int end = codeblock.indexOf("</pre>"); + String result = codeblock.substring(start, end); + result = result.replaceAll("\n\\ {4}", "\n"); + if (!codeblock.contains("\"java\"")) + { + result = Strings.escapeMarkup(result).toString(); + } + return codeblock.substring(0, start) + result + "</pre>"; + } + + private static String handleAlert(String block) + { + int openTagStart = 0; + int openTagEnd = block.indexOf("%}") + 2; + int closeTagStart = block.indexOf("{%", openTagEnd); + int closeTagEnd = block.indexOf("%}", closeTagStart) + 2; + String tag = block.substring(openTagStart + 2, openTagEnd - 2).trim(); + + Iterable<String> tagParts = Splitter.on("\\s+").split(tag); + Iterator<String> partIterator = tagParts.iterator(); + + ArrayList<String> arguments = new ArrayList<String>(); + String tagname = partIterator.next(); + for (String tagPart : tagParts) + { + arguments.add(tagPart); + } + + String alertBody = block.substring(openTagEnd, closeTagStart); + + return "<div class=\"alert alert-info\">" + alertBody + "</div>"; + } +} http://git-wip-us.apache.org/repos/asf/wicket/blob/4f31d4d7/wicket-experimental/wicket-examples-parent/wicket-examples-jar/src/main/java/org/apache/wicket/examples/base/markdown/MarkdownLabel.java ---------------------------------------------------------------------- diff --git a/wicket-experimental/wicket-examples-parent/wicket-examples-jar/src/main/java/org/apache/wicket/examples/base/markdown/MarkdownLabel.java b/wicket-experimental/wicket-examples-parent/wicket-examples-jar/src/main/java/org/apache/wicket/examples/base/markdown/MarkdownLabel.java index ddd061f..0dc3391 100644 --- a/wicket-experimental/wicket-examples-parent/wicket-examples-jar/src/main/java/org/apache/wicket/examples/base/markdown/MarkdownLabel.java +++ b/wicket-experimental/wicket-examples-parent/wicket-examples-jar/src/main/java/org/apache/wicket/examples/base/markdown/MarkdownLabel.java @@ -22,8 +22,6 @@ import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.model.IModel; import org.apache.wicket.util.convert.IConverter; -import com.petebevin.markdown.MarkdownProcessor; - public class MarkdownLabel extends Label { private static final long serialVersionUID = 1L; @@ -48,43 +46,9 @@ public class MarkdownLabel extends Label @Override public void onComponentTagBody(MarkupStream markupStream, ComponentTag openTag) { - String article = getModelObjectAsUnescapedString(); - - MarkdownProcessor processor = new MarkdownProcessor(); - String markup; - String text = processor.markdown(article); - - text = processLiquidTags(text); - - replaceComponentTagBody(markupStream, openTag, text); - } - - private String processLiquidTags(String text) - { - String markup; - StringBuilder sb = new StringBuilder(); - - int previousStart = 0; - int start = text.indexOf("{% highlight"); - while (start > 0) - { - int end = text.indexOf("{% endhighlight %}", start) + 18; - sb.append(text.substring(previousStart, start)); - - String codeblock = text.substring(start, end); - - codeblock = escapeTags(codeblock); - sb.append(codeblock); - sb.append("\n"); - - previousStart = end; - start = text.indexOf("{% highlight", end); - } - if (previousStart < text.length()) - sb.append(text.substring(previousStart)); - - markup = sb.toString(); - return markup; + String markdown = getModelObjectAsUnescapedString(); + String html = Markdown.markdownToHtml(markdown); + replaceComponentTagBody(markupStream, openTag, html); } @SuppressWarnings({ "rawtypes", "unchecked" }) @@ -105,23 +69,4 @@ public class MarkdownLabel extends Label } return null; } - - private String escapeTags(String codeblock) - { - codeblock = codeblock.replaceAll("\\{\\% highlight (.+) \\%\\}", - "<pre class=\"prettyprint linenums\" lang=\"$1\">"); - codeblock = codeblock.replaceAll("\\{\\% endhighlight \\%\\}", "</pre>"); - - int start = codeblock.indexOf(">") + 1; - int end = codeblock.indexOf("</pre>"); - String result = codeblock.substring(start, end); - result = result.replaceAll("\n\\ {4}", "\n"); - if (!codeblock.contains("\"java\"")) - { - result = result.replaceAll("&", "&"); - result = result.replaceAll("<", "<"); - result = result.replaceAll(">", ">"); - } - return codeblock.substring(0, start) + result + "</pre>"; - } } http://git-wip-us.apache.org/repos/asf/wicket/blob/4f31d4d7/wicket-experimental/wicket-examples-parent/wicket-examples-jar/src/main/java/org/apache/wicket/examples/components/Labels.md ---------------------------------------------------------------------- diff --git a/wicket-experimental/wicket-examples-parent/wicket-examples-jar/src/main/java/org/apache/wicket/examples/components/Labels.md b/wicket-experimental/wicket-examples-parent/wicket-examples-jar/src/main/java/org/apache/wicket/examples/components/Labels.md index a636c66..18492e6 100644 --- a/wicket-experimental/wicket-examples-parent/wicket-examples-jar/src/main/java/org/apache/wicket/examples/components/Labels.md +++ b/wicket-experimental/wicket-examples-parent/wicket-examples-jar/src/main/java/org/apache/wicket/examples/components/Labels.md @@ -83,7 +83,7 @@ By default, Wicket escapes all rendered text, preventing JavaScript injection attacks: {% highlight java %} - add(new Label("bad", "<a onclick=\"alert('Booh')\">Click me</a>")); + add(new Label("bad", "<a onclick=\"alert('Booh')\">Click me</a>")); {% endhighlight %} Will render safely as the following markup: http://git-wip-us.apache.org/repos/asf/wicket/blob/4f31d4d7/wicket-experimental/wicket-examples-parent/wicket-examples-jar/src/main/java/org/apache/wicket/examples/components/Links.md ---------------------------------------------------------------------- diff --git a/wicket-experimental/wicket-examples-parent/wicket-examples-jar/src/main/java/org/apache/wicket/examples/components/Links.md b/wicket-experimental/wicket-examples-parent/wicket-examples-jar/src/main/java/org/apache/wicket/examples/components/Links.md index 043f5c1..5805a48 100644 --- a/wicket-experimental/wicket-examples-parent/wicket-examples-jar/src/main/java/org/apache/wicket/examples/components/Links.md +++ b/wicket-experimental/wicket-examples-parent/wicket-examples-jar/src/main/java/org/apache/wicket/examples/components/Links.md @@ -8,7 +8,8 @@ other pages or to external sites. ### Action links When you want to perform some action on the server, triggered by a -click in the browser, you can use `Link` as the serverside component. +click in the browser, you can use [Link](http://ci.apache.org/projects/wicket/apidocs/6.0.x/org/apache/wicket/markup/html/link/Link.html) +as the serverside component. {% highlight java %} add(new Link<Void>("action") { @@ -61,7 +62,8 @@ unless you instruct otherwise. ##### Example: refresh current page -The following Java snippet just refreshes the current page: +The following Java snippet just refreshes the current page, you don't +perform have to perform any action in the `onClick` handler. {% highlight java %} add(new Link<Void>("refresh") { @@ -71,8 +73,6 @@ The following Java snippet just refreshes the current page: }); {% endhighlight %} -Note that you don't perform any action in the `onClick` handler. - ##### Example: navigate to another page The following example instructs Wicket to render the `OtherPage` as @@ -87,3 +87,144 @@ the response to your user. }); {% endhighlight %} +When you use a page instance as the argument to `setResponsePage`, +the resulting URL is relative to the session the user works in and is +not resolvable after the session has ended, resulting in a +`PageExpiredException`. + +You can also use the `setResponsePage` method using a page class and +`PageParameters`, resuling in a URL that is absolute, and can be used +even when the user's session was ended. + +{% highlight java %} + add(new Link<Void>("action") { + @Override + public void onClick() { + setResponsePage(OtherPage.class, new PageParameters().add("foo", "bar"))); + } + }); +{% endhighlight %} + +{% alert alert-info %} +<strong>Note</strong> The constructor of the page you are linking to needs to be either a +default constructor or a constructor taking `PageParameters` as the +sole parameterâotherwise Wicket will not be able to create an +instance of your page. +{% endalert %} + +## Page links + +When linking to pages, you might want your users to be able to +bookmark them. Typically an action link is not bookmarkable, since +the generated URL doesn't convey the necessary information to +re-create a particular page instance. To create bookmarkable, session +independent links you should use `BookmarkablePageLink` components. + +{% highlight java %} + add(new BookmarkablePageLink<Void>("menuitem", LinkedPage.class)); +{% endhighlight %} + +With `PageParameters` you can add additional parameters that are +passed on to your page's constructor: + +{% highlight java %} + add(new BookmarkablePageLink<Void>("grolsch", BeerPage.class, + new PageParameters().add("brand", "grolsch"))); +{% endhighlight %} + +Note that you can only create bookmarkable links to pages that have a +default constructor or a constructor taking just a PageParameters +object. + +The server does not recieve an event when the user clicks on the +link, but directly constructs the linked page and renders it. In +other words: the page that has the bookmarkable link on it never +knows if the link was clicked. + +### Bookmarkable page + +A page is considered bookmarkable when it has a default constructor, +or a constructor taking PageParameters, or both constructors. If your +page doesn't have at least one of these types of constructors, Wicket +will not know how to instantiate your page. + +The following examples show pages that are bookmarkable: + +{% highlight java %} + public class BeerPage extends WebPage { + public BeerPage() { + // default constructor + } + } +{% endhighlight %} + +An example page taking page parameters: + +{% highlight java %} + public class BeerPage extends WebPage { + public BeerPage(PageParameters parameters) { + String brand = parameters.get("brand").toString(); + } + } +{% endhighlight %} + +An example of a page that is **not** bookmarkable, since it doens't +have one of the necessary constructors: + +{% highlight java %} + public class BeerPage extends WebPage { + public BeerPage(Beer beer) { + String brand = beer.getBrand(); + } + } +{% endhighlight %} + +## Mounting pages + +You can map your bookmarkable pages to specific URLs relative to your +application context. You register the URL with the corresponding page +with the application instance. + +{% highlight java %} + public class MyApplication extends WebApplication { + @Override + protected void init() { + super.init(); + mountPage("/beer", BeerPage.class); + } + } +{% endhighlight %} + +This instructs Wicket to render URLs to the BeerPage page to look like: + + /beer/brand/grolsch + ^^^^^ + | + mountpath + +The `mountPage` method uses the [MountedMapper](http://ci.apache.org/projects/wicket/apidocs/6.0.x/org/apache/wicket/core/request/mapper/MountedMapper.html) URL encoder/decoder. + +The mount path can contain parameter placeholders, i.e. +`/mount/${foo}/path`. In that case the appropriate segment from the URL +will be accessible as named parameter "foo" in the `PageParameters`. + +Similarly when the URL is constructed, the second segment will +contain the value of the "foo" named page parameter. +Optional parameters are denoted by using a `#` instead of `$`: +`/mount/#{foo}/path/${bar}` has an optional `foo` parameter, a fixed +`/path/` part and a required `bar` parameter. + +When in doubt, parameters are matched from left to right, where +required parameters are matched before optional parameters, and +optional parameters eager (from left to right). + +## External links + +Links to URLs outside your application can be constructed using the +[ExternalLink](http://ci.apache.org/projects/wicket/apidocs/6.0.x/org/apache/wicket/markup/html/link/ExternalLink.html). +Similar to bookmarkable links, external links don't recieve a +serverside event: the user is taken directly to the external site. + +{% highlight java %} + add(new ExternalLink("google", "http://google.com")); +{% endhighlight %} http://git-wip-us.apache.org/repos/asf/wicket/blob/4f31d4d7/wicket-experimental/wicket-examples-parent/wicket-examples-jar/src/main/java/org/apache/wicket/examples/components/Pagination.md ---------------------------------------------------------------------- diff --git a/wicket-experimental/wicket-examples-parent/wicket-examples-jar/src/main/java/org/apache/wicket/examples/components/Pagination.md b/wicket-experimental/wicket-examples-parent/wicket-examples-jar/src/main/java/org/apache/wicket/examples/components/Pagination.md index 043f5c1..637db50 100644 --- a/wicket-experimental/wicket-examples-parent/wicket-examples-jar/src/main/java/org/apache/wicket/examples/components/Pagination.md +++ b/wicket-experimental/wicket-examples-parent/wicket-examples-jar/src/main/java/org/apache/wicket/examples/components/Pagination.md @@ -1,89 +1,3 @@ <div class="page-header"> - <h2>Links <small>Action links, page links, bookmarks and external links</small></h2> + <h2>Pagination</h2> </div> - -With links you can trigger actions on the server side, navigate to -other pages or to external sites. - -### Action links - -When you want to perform some action on the server, triggered by a -click in the browser, you can use `Link` as the serverside component. - -{% highlight java %} - add(new Link<Void>("action") { - @Override - public void onClick() { - // do something - } - }); -{% endhighlight %} - -For a `Link` it doesn't matter if you attach it to an `a` tag, -`input` or even a `div` or `span`. The link will generate for -non-anchor tags javascript onclick handlers automatically. So the -link of our previous example could be attached to: - -{% highlight html %} - <a href="#" wicket:id="action">Click me for some action</a> -{% endhighlight %} - -Or a `div` like: - -{% highlight html %} - <div wicket:id="action">Click me for some action</div> -{% endhighlight %} - -#### Generics of a Link - -The type parameter for a link component is used for the model the -link is supposed to work on. For example you can have a link that -increments a counter on each click: - -{% highlight java %} - add(new Link<Integer>("inc", new Model<Integer>(0)) { - @Override - public void onClick() { - int count = getModelObject(); - setModelObject(count + 1); - } - }); -{% endhighlight %} - -If your link doesn't require a model, but just performs some actions, -then you can use the `Void` type to denote such uses. - -#### Going to another page after some action - -With the `setResponsePage` method you can instruct Wicket to render a -different page. By default Wicket will re-render the current page -unless you instruct otherwise. - -##### Example: refresh current page - -The following Java snippet just refreshes the current page: - -{% highlight java %} - add(new Link<Void>("refresh") { - @Override - public void onClick() { - } - }); -{% endhighlight %} - -Note that you don't perform any action in the `onClick` handler. - -##### Example: navigate to another page - -The following example instructs Wicket to render the `OtherPage` as -the response to your user. - -{% highlight java %} - add(new Link<Void>("action") { - @Override - public void onClick() { - setResponsePage(new OtherPage()); - } - }); -{% endhighlight %} - http://git-wip-us.apache.org/repos/asf/wicket/blob/4f31d4d7/wicket-experimental/wicket-examples-parent/wicket-examples-jar/src/test/java/org/apache/wicket/examples/base/markdown/MarkdownTest.java ---------------------------------------------------------------------- diff --git a/wicket-experimental/wicket-examples-parent/wicket-examples-jar/src/test/java/org/apache/wicket/examples/base/markdown/MarkdownTest.java b/wicket-experimental/wicket-examples-parent/wicket-examples-jar/src/test/java/org/apache/wicket/examples/base/markdown/MarkdownTest.java new file mode 100644 index 0000000..224d044 --- /dev/null +++ b/wicket-experimental/wicket-examples-parent/wicket-examples-jar/src/test/java/org/apache/wicket/examples/base/markdown/MarkdownTest.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.wicket.examples.base.markdown; + +import java.io.IOException; +import java.nio.charset.Charset; + +import junit.framework.Assert; + +import org.junit.Test; + +import com.google.common.io.Resources; + +public class MarkdownTest +{ + @Test + public void testAlert() + { + String html = Markdown.markdownToHtml("{% alert %}Boo{% endalert %}"); + Assert.assertEquals("<p><div class=\"alert alert-info\">\nBoo\n</div>\n</p>\n", html); + } + + @Test + public void testAlert2() + { + String html = Markdown.markdownToHtml("{% alert alert-info %}\n" + + "The constructor of the page you are linking to needs to be either a\n" + + "default constructor or a constructor taking `PageParameters` as the\n" + + "sole parameterâotherwise Wicket will not be able to create an\n" + + "instance of your page.\n" + "{% endalert %}\n"); + + Assert.assertEquals("<p><div class=\"alert alert-info\">\n\n" + + "The constructor of the page you are linking to needs to be either a\n" + + "default constructor or a constructor taking <code>PageParameters</code> as the\n" + + "sole parameterâotherwise Wicket will not be able to create an\n" + + "instance of your page.\n\n" + "</div>\n</p>\n", html); + } + + @Test + public void testAlert3() throws IOException + { + String markdown = Resources.toString( + Resources.getResource(MarkdownTest.class, "alert3.md"), Charset.forName("utf-8")); + String html = Markdown.markdownToHtml(markdown); + String expected = Resources.toString( + Resources.getResource(MarkdownTest.class, "expected3.html"), Charset.forName("utf-8")); + Assert.assertEquals(expected, html); + } +} http://git-wip-us.apache.org/repos/asf/wicket/blob/4f31d4d7/wicket-experimental/wicket-examples-parent/wicket-examples-jar/src/test/java/org/apache/wicket/examples/base/markdown/alert3.md ---------------------------------------------------------------------- diff --git a/wicket-experimental/wicket-examples-parent/wicket-examples-jar/src/test/java/org/apache/wicket/examples/base/markdown/alert3.md b/wicket-experimental/wicket-examples-parent/wicket-examples-jar/src/test/java/org/apache/wicket/examples/base/markdown/alert3.md new file mode 100644 index 0000000..7502450 --- /dev/null +++ b/wicket-experimental/wicket-examples-parent/wicket-examples-jar/src/test/java/org/apache/wicket/examples/base/markdown/alert3.md @@ -0,0 +1,11 @@ +You can also use the setResponsePage method using a page class and +PageParameters, resuling in a URL that is absolute, and can be used +even when the user's session was ended. + +{% highlight java %} + System.out.println("Foo"); +{% endhighlight %} + +{% alert alert-info %} +Bar +{% endalert %} http://git-wip-us.apache.org/repos/asf/wicket/blob/4f31d4d7/wicket-experimental/wicket-examples-parent/wicket-examples-jar/src/test/java/org/apache/wicket/examples/base/markdown/expected3.html ---------------------------------------------------------------------- diff --git a/wicket-experimental/wicket-examples-parent/wicket-examples-jar/src/test/java/org/apache/wicket/examples/base/markdown/expected3.html b/wicket-experimental/wicket-examples-parent/wicket-examples-jar/src/test/java/org/apache/wicket/examples/base/markdown/expected3.html new file mode 100644 index 0000000..4d4ac9f --- /dev/null +++ b/wicket-experimental/wicket-examples-parent/wicket-examples-jar/src/test/java/org/apache/wicket/examples/base/markdown/expected3.html @@ -0,0 +1,13 @@ +<p>You can also use the setResponsePage method using a page class and +PageParameters, resuling in a URL that is absolute, and can be used +even when the user's session was ended.</p> + +<p><pre class="prettyprint linenums" lang="java"> +System.out.println("Foo"); +</pre> +</p> + +<p><div class="alert alert-info"> +Bar +</div> +</p>
