Author: ludovic
Date: 2008-02-25 21:04:17 +0100 (Mon, 25 Feb 2008)
New Revision: 7940
Added:
xwiki-platform/web/branches/xwiki-web-gwt-gwt14/src/main/java/com/xpn/xwiki/gwt/api/server/wysiwyg/
xwiki-platform/web/branches/xwiki-web-gwt-gwt14/src/main/java/com/xpn/xwiki/gwt/api/server/wysiwyg/Converter.java
xwiki-platform/web/branches/xwiki-web-gwt-gwt14/src/main/java/com/xpn/xwiki/gwt/api/server/wysiwyg/State.java
xwiki-platform/web/branches/xwiki-web-gwt-gwt14/src/main/java/com/xpn/xwiki/gwt/api/server/wysiwyg/StringInputStream.java
xwiki-platform/web/branches/xwiki-web-gwt-gwt14/src/main/java/com/xpn/xwiki/gwt/api/server/wysiwyg/StyleObject.java
Log:
Added api for wysiwyg editor. Meant to be moved somewhere else later
Added:
xwiki-platform/web/branches/xwiki-web-gwt-gwt14/src/main/java/com/xpn/xwiki/gwt/api/server/wysiwyg/Converter.java
===================================================================
---
xwiki-platform/web/branches/xwiki-web-gwt-gwt14/src/main/java/com/xpn/xwiki/gwt/api/server/wysiwyg/Converter.java
(rev 0)
+++
xwiki-platform/web/branches/xwiki-web-gwt-gwt14/src/main/java/com/xpn/xwiki/gwt/api/server/wysiwyg/Converter.java
2008-02-25 20:04:17 UTC (rev 7940)
@@ -0,0 +1,832 @@
+package com.xpn.xwiki.gwt.api.server.wysiwyg;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.tidy.Tidy;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/*
+ * Copyright 2007, XpertNet SARL, and individual contributors as indicated
+ * by the contributors.txt.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ *
+ * @author Christian Gmeiner
+ */
+
+
+/**
+ * TODO
+ * - class and style can coexist
+ * - make use of xwikis {style}
+ * - <br> tag broken?
+ * - rewritte style parser
+ * - write test based on html files
+ * - make check style happy
+ */
+
+/**
+ * Represents our magic converter, which is able to convert
+ * HTML to Xwiki and Xwiki to HTML.
+ *
+ * @version $Id: $
+ *
+ */
+public class Converter
+{
+ /**
+ * Identifyer for bold in xwiki syntax.
+ * Ex: *bold text*
+ */
+ private static final String BOLD_XWIKI = "*";
+
+ /**
+ * Identifyer for italic in xwiki syntax.
+ * Ex: ~~italic text~~
+ */
+ private static final String ITALIC_XWIKI = "~~";
+
+ /**
+ * Identifyer for underline in xwiki syntax.
+ * Ex: __underline text__
+ */
+ private static final String UNDERLINE_XWIKI = "__";
+
+ /**
+ * Identifyer for a new line.
+ */
+ private static final String NEW_LINE = "\n";
+
+ /**
+ * This constant represents a Node, containing pure
+ * text without tags.
+ */
+ private static final String TEXT_NODE = "#text";
+
+ /**
+ * Store all aviable styles (key is tag, object is StyleObject).
+ */
+ private static final Map STYLES = new HashMap();
+
+ /**
+ * Method to convert HTML into Xwikis markup language.
+ * @param input HTML string
+ * @return convertert string (Xwiki)
+ */
+ public static String convertHtml2XWiki(String input)
+ {
+ StringBuffer buffer = new StringBuffer();
+ State state = new State();
+
+ // create a DOM document out of our input html
+ Tidy t = new Tidy();
+
+ // dont flood us with warnigns
+ t.setQuiet(true);
+ t.setShowWarnings(false);
+
+ // parse
+ StringInputStream in = new StringInputStream(input);
+ Document doc = t.parseDOM(in, null);
+
+ // clear styles
+ STYLES.clear();
+
+ // get all childs and do a call
+ NodeList childs = doc.getChildNodes();
+
+ for (int i = 0; i < childs.getLength(); i++) {
+ node2xwiki(childs.item(i), buffer, state);
+ }
+
+ return buffer.toString().trim();
+ }
+
+ /**
+ * Convert a Node object into xwiki markup.
+ * @param node [EMAIL PROTECTED] org.w3c.dom.Node} from our parsed DOM
+ * @param buffer which is used to write our converted data in
+ * @param state [EMAIL PROTECTED] com.xpn.xwiki.wysiwyg.State} from our
+ * parent caller. It is very important, if the
+ * parent node influences our current node.
+ */
+ private static void node2xwiki(Node node, StringBuffer buffer, State
state) {
+
+ String tag = node.getNodeName();
+
+ // should never happen
+ if (tag == null) {
+ return;
+ }
+
+ if (tag.equals(TEXT_NODE)) {
+
+ // here we need to look in our state
+ // object, if the current TEXT_NODE
+ // is a real text, or a style to parse.
+ if (!state.isStyle()) {
+ // should we write the TEXT_NODE?
+ if (!state.isExclude()) {
+ buffer.append(code(node.getNodeValue()));
+ }
+ } else {
+ parseStyles(state, node.getNodeValue());
+ }
+ } else {
+
+ // to make the code cleaner, we split
+ // bigger and complxer parts into
+ // private methods.
+
+ handleBasics(tag, node, state);
+ handleLists(tag, node, state);
+ handleTables(tag, node, state);
+ handleLinks(tag, node, state);
+ handleImages(tag, node, state);
+ handleStyles(tag, node, state);
+ appendStyles(tag, node, state);
+
+ // write down our insertBefore and pricess
+ // our childs, then wirte our insertAfter.
+
+ buffer.append(state.getInsertBefore());
+
+ // get all childs and do a recursive call
+ NodeList childs = node.getChildNodes();
+
+ // create new state object for our childs,
+ // based on our current state
+ State fresh = new State(state);
+ for (int i = 0; i < childs.getLength(); i++) {
+ node2xwiki(childs.item(i), buffer, fresh);
+
+ // a problem with the current way of working is that,
+ // we need to know when we are in a table and when not.
+ // the begining of a table is very easy to find, but
+ // the end not. So we will set setInTable to false every
+ // time, but we will reset it this state. So that every
+ // child konws exactly if we are in a table or not
+ fresh.setInTable(state.isInTable());
+ }
+
+ buffer.append(state.getInsertAfter());
+
+ // it is very safe to reset the state now,
+ // because we give the state fresh to every
+ // child.
+ state.setInsertBefore("");
+ state.setInsertAfter("");
+ state.setInTable(false);
+ }
+ }
+
+ /**
+ * React on basic tags like strong, em, u,...
+ * @param tag name of the tag - e.g. strong
+ * @param node current node [EMAIL PROTECTED] org.w3c.dom.Node} which gets
processed
+ * @param state object [EMAIL PROTECTED] com.xpn.xwiki.wysiwyg.State},
+ * which is used for the final converting step.
+ */
+ private static void handleBasics(String tag, Node node, State state) {
+
+ if (tag.equals("strong") || tag.equals("b")) {
+ // bold
+ state.setInsertBefore(BOLD_XWIKI);
+ state.setInsertAfter(BOLD_XWIKI);
+
+ } else if (tag.equals("em") || tag.equals("i")) {
+ // italic
+ state.setInsertBefore(ITALIC_XWIKI);
+ state.setInsertAfter(ITALIC_XWIKI);
+
+ } else if (tag.equals("u")) {
+ // underline
+ state.setInsertBefore(UNDERLINE_XWIKI);
+ state.setInsertAfter(UNDERLINE_XWIKI);
+
+ } else if (tag.equals("br")) {
+ state.setInsertAfter("\\\\" + NEW_LINE);
+
+ } else if (tag.equals("p")) {
+
+ if (!state.isInTable()) {
+ state.setInsertAfter(NEW_LINE + NEW_LINE);
+ }
+
+ } else if (tag.equals("title")) {
+ state.setExclude(true);
+
+ } else if (tag.equals("hr")) {
+ // horizontal line
+ state.setInsertAfter(NEW_LINE + "----" + NEW_LINE);
+
+ }
+ }
+
+ /**
+ * Check if we need to convert something in connection
+ * with lists.
+ * @param tag name of the tag - e.g. strong
+ * @param node current node [EMAIL PROTECTED] org.w3c.dom.Node} which gets
processed
+ * @param state object [EMAIL PROTECTED] com.xpn.xwiki.wysiwyg.State},
+ * which is used for the final converting step.
+ */
+ private static void handleLists(String tag, Node node, State state) {
+
+ if (tag.equals("ol")) {
+ // orderd list
+ state.setOrderdList(true);
+ state.setUnorderedList(false);
+
+ } else if (tag.equals("ul")) {
+ // unorderd list
+ state.setOrderdList(false);
+ state.setUnorderedList(true);
+
+ } else if (tag.equals("li")) {
+
+ if (state.isOrderdList()) {
+ state.setInsertBefore("1. ");
+ } else if (state.isUnorderedList()) {
+ state.setInsertBefore("* ");
+ }
+
+ state.setInsertAfter(NEW_LINE);
+ }
+ }
+
+ /**
+ * Check if we need to convert something in connection
+ * with tables.
+ * @param tag name of the tag - e.g. strong
+ * @param node current node [EMAIL PROTECTED] org.w3c.dom.Node} which gets
processed
+ * @param state object [EMAIL PROTECTED] com.xpn.xwiki.wysiwyg.State},
+ * which is used for the final converting step.
+ */
+ private static void handleTables(String tag, Node node, State state) {
+
+ final String table = "{table}";
+
+ if (tag.equals("table")) {
+ state.setInsertBefore(table);
+ state.setInsertAfter(NEW_LINE + table);
+ state.setInTable(true);
+
+ // at this point we could get the informations
+ // what the total number columns are. We need simply
+ // go trhough our childs and count the number of
+ // TEXT_NODES with "col"
+
+ int count = 0;
+ NodeList childs = node.getChildNodes();
+ for (int i = 0; i < childs.getLength(); i++) {
+
+ String name = childs.item(i).getNodeName();
+ if (name != null && name.equals("col")) {
+ count++;
+ }
+ }
+
+ // was there "col" child found?
+ if (count > 0) {
+ state.setTableColumnTotal(count);
+ }
+
+ } else if (tag.equals("tr")) {
+ // set total number of columns
+ state.setTableColumnCount(0);
+ state.setTableColumnTotal(node.getChildNodes().getLength());
+
+ state.setInsertBefore(NEW_LINE);
+
+ } else if ((tag.equals("td")) || (tag.equals("th"))) {
+
+ // increase count
+ state.increaseTableColumnCount();
+
+ // insert a | only if the number of this
+ // column is lesser then the total count of
+ // columns
+ if (state.getTableColumnCount() < state.getTableColumnTotal()) {
+ state.setInsertAfter("|");
+ }
+ }
+ }
+
+ /**
+ * Check if we need handle a tags and handle them.
+ * @param tag name of the tag - e.g. strong
+ * @param node current node [EMAIL PROTECTED] org.w3c.dom.Node} which gets
processed
+ * @param state object [EMAIL PROTECTED] com.xpn.xwiki.wysiwyg.State},
which
+ * is used for the final converting step.
+ */
+ private static void handleLinks(String tag, Node node, State state) {
+
+ if (tag.equals("a")) {
+
+ final String beginTag = "[";
+ final String endTag = "]";
+ final String delimer = ">";
+ final String defaultTarget = "_self";
+
+ String url = readAttribute(node, "href");
+ String target = readAttribute(node, "target");
+ String name = "";
+
+ NodeList childs = node.getChildNodes();
+
+ // search in our content for a string obj
+ for (int j = 0; j < childs.getLength(); j++) {
+ Node child = childs.item(j);
+ String nodeName = child.getNodeName();
+
+ if (nodeName != null && nodeName.equals(TEXT_NODE)) {
+ name = child.getNodeValue();
+ }
+ }
+
+ // dont show an unvalid link
+ if (!url.equals("")) {
+
+ state.setInsertBefore(beginTag);
+
+ if (name.equals("")) {
+ state.setInsertAfter(url);
+ } else {
+
+ // now a trick part follows.
+ // if url and name are equal, we
+ // dont write a delimer and url,
+ // because something like
+ // [http://www.domain.tld>http://www.domain.tld]
+ // is nonsense.
+ // Keep in mind that "name" will be written not
+ // by us, it gets written by obj2string.
+
+ if (!url.equals(name)) {
+ state.setInsertAfter(delimer + url);
+ }
+ }
+
+ // look if we have a taret and it is not
+ // equal to defaultTarget
+ if (!target.equals("") && !target.equals(defaultTarget)) {
+ state.setInsertAfter(state.getInsertAfter() + delimer +
target);
+ }
+
+ state.setInsertAfter(state.getInsertAfter() + endTag);
+ }
+ }
+ }
+
+ /**
+ * Check if we need handle image tags and handle them.
+ * @param tag name of the tag - e.g. strong
+ * @param node current node [EMAIL PROTECTED] org.w3c.dom.Node} which gets
processed
+ * @param state object [EMAIL PROTECTED] com.xpn.xwiki.wysiwyg.State},
which
+ * is used for the final converting step.
+ */
+ private static void handleImages(String tag, Node node, State state) {
+
+ if (tag.equals("img")) {
+
+ final String beginTag = "{image:";
+ final String endTag = "}";
+ final String delimer = "|";
+
+ String src = readAttribute(node, "src");
+ String width = readAttribute(node, "width");
+ String height = readAttribute(node, "height");
+ String align = readAttribute(node, "align");
+ String halign = readAttribute(node, "halign");
+
+ // look if image tag is valid
+ if (!src.equals("")) {
+
+ // remove everything from our src, which is not needed
+ int index = src.lastIndexOf("/");
+
+ if (index > 0) {
+ src = src.substring(index + 1);
+ }
+
+ // if no width and high is given, simply write
+ // the following:
+ // {src}
+ if (width.equals("") && height.equals("")) {
+ state.setInsertBefore(beginTag + src);
+ } else {
+
+ // if width and height are the same, simply write
+ // the following
+ // {src|height}
+ if (width.equals(height)) {
+ state.setInsertBefore(beginTag + src + delimer +
height);
+ } else {
+
+ // if they are not equal, write the following
+ // {src|height|width}
+
+ // special case: if width is "", we should only write:
+ // {src|height} and not {src|height|}
+ if (width.equals("")) {
+ state.setInsertBefore(beginTag + src + delimer +
height);
+ } else {
+ state.setInsertBefore(beginTag + src + delimer
+ + height + delimer +
width);
+ }
+ }
+ }
+
+ // here we analyse the aligment stuff
+ String aligment = "";
+
+ // look if there is an align
+ if (!align.equals("")) {
+ aligment = delimer + align;
+ }
+
+ // look if there is a halign
+ if (!halign.equals("")) {
+
+ if (aligment.equals("")) {
+ aligment = delimer;
+ }
+
+ aligment = aligment + delimer + halign;
+ }
+
+ // do we need to add aligment data?
+ if (!aligment.equals("")) {
+ state.setInsertBefore(state.getInsertBefore() + aligment);
+ }
+
+ // add end tag
+ state.setInsertAfter(state.getInsertAfter() + endTag);
+ }
+ }
+ }
+
+ /**
+ * Check if we need handle style tags and handle them.
+ * @param tag name of the tag - e.g. strong
+ * @param node current node [EMAIL PROTECTED] org.w3c.dom.Node} which gets
processed
+ * @param state object [EMAIL PROTECTED] com.xpn.xwiki.wysiwyg.State},
which
+ * is used for the final converting step.
+ */
+ private static void handleStyles(String tag, Node node, State state) {
+
+ if (tag.equals("style")) {
+
+ // indicate, that the next pared #text
+ // will contain style informations to
+ // parse.
+ state.setStyle(true);
+ }
+ }
+
+ /**
+ * Convert child od <style></style> and add it to STYLES.
+ * @param state object [EMAIL PROTECTED] com.xpn.xwiki.wysiwyg.State},
+ * which is used for the final converting step.
+ * @param input String, which contains the styles to parse
+ */
+ private static void parseStyles(State state, String input) {
+
+ int index = 0;
+
+ // reset style indicator
+ state.setStyle(false);
+
+ // we are working on a copy
+ String in = input.trim();
+
+ // remove <!-- -->
+ if (in.startsWith("<!--")) {
+ in = in.substring(3, in.length() - 3);
+ }
+
+ while (index < in.length() - 1) {
+
+ int start = in.indexOf("{", index);
+ int end = in.indexOf("}", index);
+
+ String tag = in.substring(index, start).trim();
+ String sub = in.substring(start + 1, end - 1).trim();
+
+ // remove comments from tag
+ if (tag.contains("/*")) {
+ int s = tag.indexOf("/*");
+ int e = tag.lastIndexOf("*/");
+
+ // remove it
+ tag = tag.substring(0, s) + tag.substring(e + 2,
tag.length()).trim();
+ }
+
+ StyleObject obj = new StyleObject();
+ parseStyleBlock(obj, sub);
+
+ // only add styleobj if it is dirty
+ if (obj.isDirty()) {
+
+ // look if there is a "," in the tag
+ String[] tags = tag.split(",");
+
+ if (tags.length > 0) {
+
+ for (int i = 0; i < tags.length; i++) {
+ STYLES.put(tags[i].trim(), obj);
+ }
+
+ } else {
+ STYLES.put(tag, obj);
+ }
+ }
+
+ index = end + 1;
+ }
+ }
+
+ /**
+ * This method is used to parse many style definitions, like:
+ * option : value; option : value; ...
+ * @param style StyleObject [EMAIL PROTECTED] StyleObject} used to fill
+ * @param input out input String with all data to parse
+ */
+ private static void parseStyleBlock(StyleObject style, String input) {
+
+ String[] parts = input.split(";");
+
+ for (int i = 0; i < parts.length; i++) {
+ parseOneStyle(style, parts[i]);
+ }
+ }
+
+ /**
+ * Little helper ot parse one single line of a style.
+ * @param style StyleObject [EMAIL PROTECTED] StyleObject} used to fill
+ * @param input our input String with data to parse
+ */
+ private static void parseOneStyle(StyleObject style, String input) {
+
+ // a line of a style has the following syntases:
+ // option:value
+
+ String[] parts = input.split(":");
+
+ String option = parts[0].trim();
+ String value = parts[1].trim();
+
+ // check for supported options
+ if (option.contains("font-weight")) {
+ if (value.contains("bold")) {
+ style.setBold(true);
+ }
+ }
+
+ if (option.contains("font-style")) {
+ if (value.contains("italic")) {
+ style.setItalic(true);
+ }
+ }
+
+ if (option.contains("font-size")) {
+ style.setFontSize(value);
+ }
+
+ if (option.contains("font-family")) {
+ style.setFontFamily(value);
+ }
+
+ if (option.contains("color")) {
+ style.setColor(value);
+ }
+
+ if (option.contains("width")) {
+ style.setWidth(value);
+ }
+
+ if (option.contains("hight")) {
+ style.setHight(value);
+ }
+ }
+
+ /**
+ * Append any found style.
+ * @param tag name of the tag - e.g. strong
+ * @param node current node [EMAIL PROTECTED] org.w3c.dom.Node} which gets
processed
+ * @param state object [EMAIL PROTECTED] State}, which is used for the
final converting
+ * step.
+ */
+ private static void appendStyles(String tag, Node node, State state) {
+
+ String style = readAttribute(node, "style");
+
+ // only try to append a stlye, if we
+ // have found styles. There exists only
+ // one special case: a style can be also
+ // defined in attribute "style"
+ if (STYLES.isEmpty() && style.equals("")) {
+ return;
+ }
+
+ StyleObject obj = null;
+
+ // look if there is a style and if it contains
+ // a ":" - is needed because of the style format:
+ // option : value
+ if (!style.equals("") && style.contains(":")) {
+
+ // create a new object and parse
+ // the style
+ obj = new StyleObject();
+ parseStyleBlock(obj, style);
+
+ // if our style is not dirty,
+ // mark it as null, so that
+ // we will not try to append this
+ // style.
+ if (!obj.isDirty()) {
+ obj = null;
+ }
+
+ } else {
+
+ // read class attribute and try to find a
+ // StyleObject
+ String styleClass = readAttribute(node, "class");
+ obj = findStyle(tag, styleClass);
+ }
+
+ // have we found a suitable StyleObject?
+ if (obj == null) {
+ return;
+ }
+
+ // append our StyleObject
+ String before = state.getInsertBefore();
+ String after = state.getInsertAfter();
+
+ // append styles
+ if (obj.isBold()) {
+ before = before + BOLD_XWIKI;
+ after = BOLD_XWIKI + after;
+ }
+
+ if (obj.isItalic()) {
+ before = before + ITALIC_XWIKI;
+ after = ITALIC_XWIKI + after;
+ }
+
+ // try to generate xwiki style
+ String styleBlock = generateStyleBlock(obj);
+
+ if (!styleBlock.equals("")) {
+ before = before + styleBlock;
+ after = "{style}" + after;
+ }
+
+ state.setInsertBefore(before);
+ state.setInsertAfter(after);
+ }
+
+ /**
+ * Little helper to read out a wanted attribute.
+ * @param node from [EMAIL PROTECTED] org.w3c.dom.Node} which we want an
attribute
+ * @param attribute the name of the wanted attribute
+ * @return the value of the wanted attriubte or ""
+ */
+ private static String readAttribute(Node node, String attribute) {
+
+ String result = "";
+
+ NamedNodeMap attributes = node.getAttributes();
+
+ // go throuh our attributes and look for attribute
+ for (int j = 0; j < attributes.getLength(); j++) {
+ Node attr = attributes.item(j);
+
+ if (attr.getNodeName().equals(attribute)) {
+ result = attr.getNodeValue();
+ break;
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * This method searches for a suitable StyleObject.
+ * @param tag String representation of the tag - e.g. div
+ * @param styleclass name of the style class to use
+ * @return if a style was found a valid instance of StyleObject
+ * else null
+ */
+ private static StyleObject findStyle(String tag, String styleclass) {
+ StyleObject obj = null;
+
+ // we must look now, if we can find a suitable StyleObject.
+ // so we are looking with the following keys
+ // * tag.styleClass
+ // * .styleClass
+ // * tag
+
+ if (!styleclass.equals("")) {
+
+ String stlye = "." + styleclass;
+ obj = (StyleObject) STYLES.get(tag + stlye);
+
+ // not found... try it with an other name
+ if (obj == null) {
+ obj = (StyleObject) STYLES.get(stlye);
+ }
+ }
+
+ if (obj == null) {
+ obj = (StyleObject) STYLES.get(tag);
+ }
+
+ return obj;
+ }
+
+ private static String generateStyleBlock(StyleObject obj) {
+
+ StringBuffer buffer = new StringBuffer();
+
+ // xwiki has support for more advanced styles
+ // it useses for this {style}
+ if (obj.isStyleTag()) {
+ buffer.append("{style:");
+
+ if (obj.getFontSize() != null) {
+ buffer.append("font-size=");
+ buffer.append(obj.getFontSize());
+ buffer.append("|");
+ }
+
+ if (obj.getColor() != null) {
+ buffer.append("color=");
+ buffer.append(obj.getColor());
+ buffer.append("|");
+ }
+
+ if (obj.getFontFamily() != null) {
+ buffer.append("font-family=");
+ buffer.append(obj.getFontFamily());
+ buffer.append("|");
+ }
+
+ if (obj.getWidth() != null) {
+ buffer.append("width=");
+ buffer.append(obj.getWidth());
+ buffer.append("|");
+ }
+
+ if (obj.getHight() != null) {
+ buffer.append("height=");
+ buffer.append(obj.getHight());
+ buffer.append("|");
+ }
+
+ // remove last |
+ if (buffer.length() > 7) {
+ buffer.delete(buffer.length() - 1, buffer.length());
+ }
+
+ buffer.append("}");
+ }
+
+ return buffer.toString();
+ }
+
+ /**
+ * @param input String to code for xwiki syntax
+ * @return xwiki compatible String
+ */
+ private static String code(String input) {
+
+ String result = input;
+
+ // convert a \ to \\\
+ result = result.replace("\\", "\\\\\\");
+
+ return result;
+ }
+}
Added:
xwiki-platform/web/branches/xwiki-web-gwt-gwt14/src/main/java/com/xpn/xwiki/gwt/api/server/wysiwyg/State.java
===================================================================
---
xwiki-platform/web/branches/xwiki-web-gwt-gwt14/src/main/java/com/xpn/xwiki/gwt/api/server/wysiwyg/State.java
(rev 0)
+++
xwiki-platform/web/branches/xwiki-web-gwt-gwt14/src/main/java/com/xpn/xwiki/gwt/api/server/wysiwyg/State.java
2008-02-25 20:04:17 UTC (rev 7940)
@@ -0,0 +1,256 @@
+package com.xpn.xwiki.gwt.api.server.wysiwyg;
+
+/*
+ * Copyright 2007, XpertNet SARL, and individual contributors as indicated
+ * by the contributors.txt.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ *
+ * @author Christian Gmeiner
+ */
+
+
+/**
+ * This class represnets a so called State. In
+ * it are stored informations which are used for
+ * processing of found child tags.
+ *
+ * @version $Id: $
+ */
+public class State
+{
+ /**
+ * @see #isOrderdList()
+ */
+ private boolean orderdList;
+
+ /**
+ * @see #isUnorderedList()
+ */
+ private boolean unorderedList;
+
+ /**
+ * @see #getInsertBefore()
+ */
+ private String insertBefore;
+
+ /**
+ * @see #getInsertAfter()
+ */
+ private String insertAfter;
+
+ /**
+ * @see #getTableColumnTotal()
+ */
+ private int tableColumnTotal;
+
+ /**
+ * @see #getTableColumnCount()
+ */
+ private int tableColumnCount;
+
+ /**
+ * @see #isExclude()
+ */
+ private boolean exclude;
+
+ /**
+ * @see #isStyle()
+ */
+ private boolean style;
+
+ /**
+ * @see #isInTable()
+ */
+ private boolean inTable;
+
+ /**
+ * Constructor.
+ */
+ public State() {
+ this.orderdList = false;
+ this.unorderedList = false;
+ this.insertBefore = "";
+ this.insertAfter = "";
+ this.tableColumnTotal = 0;
+ this.tableColumnCount = 0;
+ this.exclude = false;
+ this.style = false;
+ this.inTable = false;
+ }
+
+ /**
+ * Constructor.
+ * @param other use parent State to
+ * setup this State object
+ */
+ public State(State other) {
+ this.orderdList = other.isOrderdList();
+ this.unorderedList = other.isUnorderedList();
+ this.insertBefore = "";
+ this.insertAfter = "";
+ this.tableColumnTotal = other.getTableColumnTotal();
+ this.tableColumnCount = other.getTableColumnCount();
+ this.exclude = other.isExclude();
+ this.style = other.isStyle();
+ this.inTable = other.isInTable();
+ }
+
+ /**
+ * @return the orderdList
+ */
+ public boolean isOrderdList() {
+ return orderdList;
+ }
+ /**
+ * @param orderdList the orderdList to set
+ */
+ public void setOrderdList(boolean orderdList) {
+ this.orderdList = orderdList;
+ }
+ /**
+ * @return the unorderedList
+ */
+ public boolean isUnorderedList() {
+ return unorderedList;
+ }
+ /**
+ * @param unorderedList the unorderedList to set
+ */
+ public void setUnorderedList(boolean unorderedList) {
+ this.unorderedList = unorderedList;
+ }
+
+ /**
+ * @return the insertAfter
+ */
+ public String getInsertAfter() {
+ return insertAfter;
+ }
+
+ /**
+ * @param insertAfter the insertAfter to set
+ */
+ public void setInsertAfter(String insertAfter) {
+ this.insertAfter = insertAfter;
+ }
+
+ /**
+ * @return the insertBefore
+ */
+ public String getInsertBefore() {
+ return insertBefore;
+ }
+
+ /**
+ * @param insertBefore the insertBefore to set
+ */
+ public void setInsertBefore(String insertBefore) {
+ this.insertBefore = insertBefore;
+ }
+
+ /**
+ * @return the tableColumnTotal
+ */
+ public int getTableColumnTotal() {
+ return tableColumnTotal;
+ }
+
+ /**
+ * @param tableColumnTotal the tableColumnTotal to set
+ */
+ public void setTableColumnTotal(int tableColumnTotal) {
+
+ // it is only possible to change this value, if
+ // it is 0. Else we could get some wired results
+ // with table handling.
+ if (this.tableColumnTotal == 0) {
+ this.tableColumnTotal = tableColumnTotal;
+ }
+ }
+
+ /**
+ * @return the tableColumnCount, which is needed
+ * by the html2xwiki converter, to know when
+ * to place the | seperator between columns in
+ * tables.
+ */
+ public int getTableColumnCount() {
+ return tableColumnCount;
+ }
+
+ /**
+ * @param tableColumnCount the tableColumnCount to set
+ */
+ public void setTableColumnCount(int tableColumnCount) {
+ this.tableColumnCount = tableColumnCount;
+ }
+
+ /**
+ * Little helper to make it easier to increase tableColumnCount.
+ */
+ public void increaseTableColumnCount() {
+ this.tableColumnCount++;
+ }
+
+ /**
+ * @return if the the childs of the current
+ * node should be wirtten to the buffer or not
+ */
+ public boolean isExclude() {
+ return exclude;
+ }
+
+ /**
+ * @param exclude define, if the the childs of the current
+ * node should be wirtten to the buffer or not
+ */
+ public void setExclude(boolean exclude) {
+ this.exclude = exclude;
+ }
+
+ /**
+ * @return true, if the following #TEXT node contains styles
+ * to parse
+ */
+ public boolean isStyle() {
+ return style;
+ }
+
+ /**
+ * @param style does the following #TEXT node contains styles
+ * to parse?
+ */
+ public void setStyle(boolean style) {
+ this.style = style;
+ }
+
+ /**
+ * @return the inTable
+ */
+ public boolean isInTable()
+ {
+ return inTable;
+ }
+
+ /**
+ * @param inTable the inTable to set
+ */
+ public void setInTable(boolean inTable)
+ {
+ this.inTable = inTable;
+ }
+}
Added:
xwiki-platform/web/branches/xwiki-web-gwt-gwt14/src/main/java/com/xpn/xwiki/gwt/api/server/wysiwyg/StringInputStream.java
===================================================================
---
xwiki-platform/web/branches/xwiki-web-gwt-gwt14/src/main/java/com/xpn/xwiki/gwt/api/server/wysiwyg/StringInputStream.java
(rev 0)
+++
xwiki-platform/web/branches/xwiki-web-gwt-gwt14/src/main/java/com/xpn/xwiki/gwt/api/server/wysiwyg/StringInputStream.java
2008-02-25 20:04:17 UTC (rev 7940)
@@ -0,0 +1,77 @@
+package com.xpn.xwiki.gwt.api.server.wysiwyg;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+
+/*
+ * Copyright 2007, XpertNet SARL, and individual contributors as indicated
+ * by the contributors.txt.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ *
+ * @author Christian Gmeiner
+ */
+
+/**
+ * This is our own implementation of a StringInputStream, based on
+ * InputStream.
+ *
+ * @version $Id: $
+ *
+ */
+public class StringInputStream extends InputStream
+{
+
+ /**
+ * String,, which is used as source for this InputStream.
+ */
+ private String data;
+
+ /**
+ * aviable chars in this InputStream.
+ */
+ private int aviable;
+
+ /**
+ * @param in String which is used for this InputStream
+ */
+ public StringInputStream(String in) {
+ data = in;
+ aviable = in.length();
+ }
+
+ /**
+ * [EMAIL PROTECTED]
+ * @see java.io.InputStream#read()
+ */
+ public int read() throws IOException {
+
+ // look if there is data aviable
+ if (aviable == 0) {
+ return -1;
+ }
+
+ // calculate new index
+ int index = data.length() - aviable;
+
+ aviable--;
+
+ // return char at index
+ return data.charAt(index);
+ }
+
+}
Added:
xwiki-platform/web/branches/xwiki-web-gwt-gwt14/src/main/java/com/xpn/xwiki/gwt/api/server/wysiwyg/StyleObject.java
===================================================================
---
xwiki-platform/web/branches/xwiki-web-gwt-gwt14/src/main/java/com/xpn/xwiki/gwt/api/server/wysiwyg/StyleObject.java
(rev 0)
+++
xwiki-platform/web/branches/xwiki-web-gwt-gwt14/src/main/java/com/xpn/xwiki/gwt/api/server/wysiwyg/StyleObject.java
2008-02-25 20:04:17 UTC (rev 7940)
@@ -0,0 +1,187 @@
+package com.xpn.xwiki.gwt.api.server.wysiwyg;
+
+/*
+ * Copyright 2007, XpertNet SARL, and individual contributors as indicated
+ * by the contributors.txt.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ *
+ * @author Christian Gmeiner
+ */
+
+
+
+/**
+ * @version $Id: $
+ *
+ */
+public class StyleObject
+{
+
+ /**
+ * @see #isBold()
+ */
+ private boolean bold;
+
+ /**
+ * @see #isItalic()
+ */
+ private boolean italic;
+
+ /**
+ * @see #isDirty()
+ */
+ private boolean dirty;
+
+ /**
+ * @see #isStyleTag()
+ */
+ private boolean styleTag;
+
+ /**
+ * @see #getFontSize()
+ */
+ private String fontSize;
+
+ /**
+ * @see #getFontFamily()
+ */
+ private String fontFamily;
+
+ /**
+ * @see #getColor()
+ */
+ private String color;
+
+ /**
+ * @see #getWidth()
+ */
+ private String width;
+
+ /**
+ * @see #getHight()
+ */
+ private String hight;
+
+ /**
+ * Constructor.
+ */
+ public StyleObject() {
+ this.bold = false;
+ this.italic = false;
+ this.dirty = false;
+ this.styleTag = false;
+ }
+
+ /**
+ * @return the bold
+ */
+ public boolean isBold() {
+ return bold;
+ }
+
+ /**
+ * @param bold the bold to set
+ */
+ public void setBold(boolean bold) {
+ this.dirty = true;
+ this.bold = bold;
+ }
+
+ /**
+ * @return the italic
+ */
+ public boolean isItalic() {
+ return italic;
+ }
+
+ /**
+ * @param italic the italic to set
+ */
+ public void setItalic(boolean italic) {
+ this.dirty = true;
+ this.italic = italic;
+ }
+
+ /**
+ * @return if our StyleObject is dirty
+ */
+ public boolean isDirty() {
+ return dirty;
+ }
+
+ public boolean isStyleTag() {
+ return styleTag;
+ }
+
+ public void setStyleTag(boolean styleTag) {
+ this.styleTag = styleTag;
+ }
+
+
+ public String getFontSize() {
+ return fontSize;
+ }
+
+ public void setFontSize(String fontSize) {
+ this.fontSize = fontSize;
+ this.styleTag = true;
+ this.dirty = true;
+ }
+
+
+ public String getFontFamily() {
+ return fontFamily;
+ }
+
+ public void setFontFamily(String fontFamily) {
+ this.fontFamily = fontFamily;
+ this.styleTag = true;
+ this.dirty = true;
+ }
+
+
+ public String getColor() {
+ return color;
+ }
+
+ public void setColor(String color) {
+ this.color = color;
+ this.styleTag = true;
+ this.dirty = true;
+ }
+
+
+ public String getWidth() {
+ return width;
+ }
+
+ public void setWidth(String width) {
+ this.width = width;
+ this.styleTag = true;
+ this.dirty = true;
+ }
+
+ public String getHight() {
+ return hight;
+ }
+
+ public void setHight(String hight) {
+ this.hight = hight;
+ this.styleTag = true;
+ this.dirty = true;
+ }
+}
_______________________________________________
notifications mailing list
[email protected]
http://lists.xwiki.org/mailman/listinfo/notifications