Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

completed jquery mixing template aka htmlcomposer, still full css

matching missing
  • Loading branch information...
commit ab0cfd2522c9f7fe82ea5cfa82f89cd52ef7c0ca 1 parent 020e86e
@michelegonella authored
View
18 zen-base/src/main/java/com/nominanuda/xml/SAXPipeline.java
@@ -92,6 +92,18 @@ public SAXPipeline complete() {
}
return this;
}
+
+ public SAXResult build(Result result) {
+ if(! completed) {
+ complete();
+ }
+ try {
+ return (SAXResult)buildInternal(result);
+ } catch (TransformerConfigurationException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
public Runnable build(final Source source, final Result result) {
if(! completed) {
complete();
@@ -99,7 +111,7 @@ public Runnable build(final Source source, final Result result) {
return new Runnable() {
public void run() {
try {
- txFactory.newTransformer().transform(source, build(result));
+ txFactory.newTransformer().transform(source, buildInternal(result));
} catch (Exception e) {
throw new RuntimeException(e);
}
@@ -113,7 +125,7 @@ public Runnable build(final SAXEmitter emitter, final SAXResult result) {
return new Runnable() {
public void run() {
try {
- emitter.toSAX(((SAXResult)build(result)).getHandler());
+ emitter.toSAX(((SAXResult)buildInternal(result)).getHandler());
} catch (Exception e) {
throw new RuntimeException(e);
}
@@ -133,7 +145,7 @@ private TransformerHandler buildTranformerHandler(Object c) throws TransformerCo
}
}
- private Result build(final Result result) throws TransformerConfigurationException {
+ private Result buildInternal(final Result result) throws TransformerConfigurationException {
Check.illegalstate.assertTrue(completed);
Result nextRes = result;
Iterator<Object> itr = components.iterator();
View
247 zen-webservice/src/main/java/com/nominanuda/web/htmlcomposer/DomManipulationHandler.java
@@ -0,0 +1,247 @@
+/*
+ * Copyright 2008-2011 the original author or authors.
+ *
+ * Licensed 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 com.nominanuda.web.htmlcomposer;
+
+import java.util.Stack;
+
+import javax.xml.transform.sax.SAXResult;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+
+import com.nominanuda.code.Nullable;
+import com.nominanuda.lang.Fun0;
+import com.nominanuda.lang.Strings;
+import com.nominanuda.lang.Tuple2;
+import com.nominanuda.xml.ForwardingTransformerHandlerBase;
+import com.nominanuda.xml.SwallowingTransformerHandlerBase;
+import com.nominanuda.xml.SaxBuffer.SaxBit;
+
+public abstract class DomManipulationHandler extends ForwardingTransformerHandlerBase {
+ private int nestingLevel = 0;
+ private final DomManipulationStmt stmt;
+ private Stack<Tuple2<Integer, Fun0<Void>>> triggerStack = new Stack<Tuple2<Integer,Fun0<Void>>>();
+ private ContentHandler liveContentHandler;
+ private final static ContentHandler devNull = new SwallowingTransformerHandlerBase();
+
+ public static DomManipulationHandler build(DomManipulationStmt stmt) {
+ switch (stmt.getOperation()) {
+ case html:
+ return new HtmlHandler(stmt);
+ case replaceWith:
+ return new ReplaceWithHandler(stmt);
+ case before:
+ return new BeforeHandler(stmt);
+ case after:
+ return new AfterHandler(stmt);
+ case prepend:
+ return new PrependHandler(stmt);
+ case append:
+ return new AppendHandler(stmt);
+ }
+ throw new IllegalStateException("unsupported operation:" + stmt.getOperation().name());
+ }
+
+ private DomManipulationHandler(DomManipulationStmt domManipulationStmt) {
+ stmt = domManipulationStmt;
+ }
+
+ protected String getSelector() {
+ return stmt.getSelector();
+ }
+
+ @Override
+ public void startElement(String uri, String localName, String qName,
+ Attributes atts) throws SAXException {
+ nestingLevel++;
+ if(matches(localName, atts)) {
+ onMatchedStartElement(uri, localName, qName, atts);
+ } else {
+ super.startElement(uri, localName, qName, atts);
+ }
+ }
+
+ protected abstract void onMatchedStartElement(String uri, String localName, String qName,
+ Attributes atts) throws SAXException;
+
+ private void onTriggerEndElement() {
+ Fun0<Void> f = triggerStack.pop().get1();
+ f.apply();
+ }
+
+ protected void pushTriggerEndElement(Fun0<Void> trigger) {
+ triggerStack.push(new Tuple2<Integer, Fun0<Void>>(nestingLevel, trigger));
+ };
+
+ @Override
+ public void endElement(String uri, String localName, String qName)
+ throws SAXException {
+ if(! triggerStack.isEmpty() && triggerStack.peek().get0() == nestingLevel) {
+ onTriggerEndElement();
+ } else {
+ super.endElement(uri, localName, qName);
+ }
+ nestingLevel--;
+ }
+
+ //TODO
+ private boolean matches(String tag, Attributes atts) {
+ if(getSelector().startsWith(".")) {
+ if(classMatches(atts.getValue("class"), getSelector().substring(1))) {
+ return true;
+ }
+ } else if(true) {
+ if(tag.equals(getSelector())) {
+ return true;
+ }
+ }
+ return false;//TODO
+ }
+
+ private boolean classMatches(@Nullable String clsAttr, String targetClass) {
+ return clsAttr != null && Strings.splitAndTrim(clsAttr, "\\s+").contains(targetClass);
+ }
+
+ protected void turnOnOutput() {
+ if(liveContentHandler == null) {
+ liveContentHandler = getTarget();
+ }
+ setResult(new SAXResult(liveContentHandler));
+ }
+ protected void turnOffOutput() {
+ if(liveContentHandler == null) {
+ liveContentHandler = getTarget();
+ }
+ setResult(new SAXResult(devNull));
+ }
+ protected void streamFragment() throws SAXException {
+ ContentHandler ch = getTarget();
+ for(SaxBit b : stmt.getSaxBuffer().getBits()) {
+ b.send(ch);
+ }
+ }
+
+ private static class HtmlHandler extends DomManipulationHandler {
+ public HtmlHandler(DomManipulationStmt domManipulationStmt) {
+ super(domManipulationStmt);
+ }
+ @Override
+ protected void onMatchedStartElement(final String uri, final String localName,
+ final String qName, final Attributes atts) throws SAXException {
+ turnOffOutput();
+ pushTriggerEndElement(new Fun0<Void>() {
+ public Void apply() {
+ try {
+ turnOnOutput();
+ getTarget().startElement(uri, localName, qName, atts);
+ streamFragment();
+ getTarget().endElement(uri, localName, qName);
+ return null;
+ } catch (SAXException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ });
+ }
+ }
+ private static class ReplaceWithHandler extends DomManipulationHandler {
+ public ReplaceWithHandler(DomManipulationStmt domManipulationStmt) {
+ super(domManipulationStmt);
+ }
+ @Override
+ protected void onMatchedStartElement(final String uri, final String localName,
+ final String qName, final Attributes atts) throws SAXException {
+ turnOffOutput();
+ pushTriggerEndElement(new Fun0<Void>() {
+ public Void apply() {
+ try {
+ turnOnOutput();
+ streamFragment();
+ return null;
+ } catch (SAXException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ });
+ }
+ }
+ private static class BeforeHandler extends DomManipulationHandler {
+ public BeforeHandler(DomManipulationStmt domManipulationStmt) {
+ super(domManipulationStmt);
+ }
+ @Override
+ protected void onMatchedStartElement(final String uri, final String localName,
+ final String qName, final Attributes atts) throws SAXException {
+ streamFragment();
+ getTarget().startElement(uri, localName, qName, atts);
+ }
+ }
+ private static class PrependHandler extends DomManipulationHandler {
+ public PrependHandler(DomManipulationStmt domManipulationStmt) {
+ super(domManipulationStmt);
+ }
+ @Override
+ protected void onMatchedStartElement(final String uri, final String localName,
+ final String qName, final Attributes atts) throws SAXException {
+ getTarget().startElement(uri, localName, qName, atts);
+ streamFragment();
+ }
+ }
+ private static class AppendHandler extends DomManipulationHandler {
+ public AppendHandler(DomManipulationStmt domManipulationStmt) {
+ super(domManipulationStmt);
+ }
+ @Override
+ protected void onMatchedStartElement(final String uri, final String localName,
+ final String qName, final Attributes atts) throws SAXException {
+ getTarget().startElement(uri, localName, qName, atts);
+ pushTriggerEndElement(new Fun0<Void>() {
+ public Void apply() {
+ try {
+ streamFragment();
+ getTarget().endElement(uri, localName, qName);
+ return null;
+ } catch (SAXException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ });
+ }
+ }
+ private static class AfterHandler extends DomManipulationHandler {
+ public AfterHandler(DomManipulationStmt domManipulationStmt) {
+ super(domManipulationStmt);
+ }
+ @Override
+ protected void onMatchedStartElement(final String uri, final String localName,
+ final String qName, final Attributes atts) throws SAXException {
+ getTarget().startElement(uri, localName, qName, atts);
+ pushTriggerEndElement(new Fun0<Void>() {
+ public Void apply() {
+ try {
+ getTarget().endElement(uri, localName, qName);
+ streamFragment();
+ return null;
+ } catch (SAXException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ });
+ }
+ }
+
+}
View
8 zen-webservice/src/main/java/com/nominanuda/web/htmlcomposer/DomManipulationStmt.java
@@ -22,10 +22,10 @@
@Immutable
public class DomManipulationStmt {
- final String selector;
- final ObjectFactory<SaxBuffer> saxBufferFactory;
- final DomOp operation;
- SaxBuffer saxBuffer;
+ private final String selector;
+ private final ObjectFactory<SaxBuffer> saxBufferFactory;
+ private final DomOp operation;
+ private SaxBuffer saxBuffer;
public DomManipulationStmt(String selector, ObjectFactory<SaxBuffer> saxBufferFactory,
DomOp operation) {
View
48 zen-webservice/src/main/java/com/nominanuda/web/htmlcomposer/HtmlFragmentChecker.java
@@ -1,48 +0,0 @@
-/*
- * Copyright 2008-2011 the original author or authors.
- *
- * Licensed 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 com.nominanuda.web.htmlcomposer;
-
-import org.xml.sax.Attributes;
-import org.xml.sax.SAXException;
-
-import com.nominanuda.web.http.HttpProtocol;
-import com.nominanuda.xml.ForwardingTransformerHandlerBase;
-
-public class HtmlFragmentChecker extends ForwardingTransformerHandlerBase implements HttpProtocol {
-
- public void startDocument() throws SAXException {
- }
-
- public void endDocument() throws SAXException {
- }
-
- public void startElement(String uri, String localName, String qName,
- Attributes atts) throws SAXException {
- if(! HTMLNS.equals(uri)) {
- uri = HTMLNS;
- }
- super.startElement(uri, localName, qName, atts);
- }
-
- public void endElement(String uri, String localName, String qName)
- throws SAXException {
- if(! HTMLNS.equals(uri)) {
- uri = HTMLNS;
- }
- super.endElement(uri, localName, qName);
- }
-
-}
View
46 zen-webservice/src/main/java/com/nominanuda/web/htmlcomposer/HtmlSaxPage.java
@@ -16,35 +16,49 @@
package com.nominanuda.web.htmlcomposer;
import java.util.LinkedList;
+import java.util.List;
+
+import javax.xml.transform.sax.SAXResult;
+import javax.xml.transform.sax.TransformerHandler;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;
+import com.nominanuda.lang.InstanceFactory;
+import com.nominanuda.web.http.HttpProtocol;
import com.nominanuda.xml.SAXEmitter;
+import com.nominanuda.xml.SAXPipeline;
import com.nominanuda.xml.SaxBuffer;
-import com.nominanuda.xml.SaxBuffer.SaxBit;
-
-//TODO replace html in split blocks
-public class HtmlSaxPage implements SAXEmitter {
- String htmlns = "http://www.w3.org/1999/xhtml";
- LinkedList<SaxBit> bits = new LinkedList<SaxBit>();
- public HtmlSaxPage() {
- bits.add(new SaxBuffer.StartElement(htmlns, "body", "body", new AttributesImpl()));
- bits.add(new SaxBuffer.EndElement(htmlns, "body", "body"));
- }
+public class HtmlSaxPage implements SAXEmitter, HttpProtocol {
+ private static final String BODY = "body";
+ private static final String HEAD = "head";
+ private final List<DomManipulationStmt> stmts = new LinkedList<DomManipulationStmt>();
public void applyStmt(DomManipulationStmt domManipulationStmt) {
- JQuerySaxMatcher m = new JQuerySaxMatcher(domManipulationStmt);
- for(int i = 0; i < bits.size();) {
- i = m.match(bits, i);
- }
+ stmts.add(domManipulationStmt);
}
public void toSAX(ContentHandler ch) throws SAXException {
- for(SaxBit b : bits) {
- b.send(ch);
+ ContentHandler x = buildPipe(ch);
+ new SaxBuffer.StartElement(HTMLNS, HEAD, HEAD, new AttributesImpl()).send(x);
+ new SaxBuffer.EndElement(HTMLNS, HEAD, HEAD).send(x);
+ new SaxBuffer.StartElement(HTMLNS, BODY, BODY, new AttributesImpl()).send(x);
+ new SaxBuffer.EndElement(HTMLNS, BODY, BODY).send(x);
+ }
+
+ private ContentHandler buildPipe(ContentHandler ch) {
+ SAXPipeline p = new SAXPipeline();
+ for(DomManipulationStmt stmt : stmts) {
+ TransformerHandler instance = buildHandler(stmt);
+ p.add(new InstanceFactory<TransformerHandler>(instance));
}
+ ContentHandler x = p.complete().build(new SAXResult(ch)).getHandler();
+ return x;
+ }
+
+ private TransformerHandler buildHandler(DomManipulationStmt stmt) {
+ return DomManipulationHandler.build(stmt);
}
}
View
95 zen-webservice/src/main/java/com/nominanuda/web/htmlcomposer/JQuerySaxMatcher.java
@@ -1,95 +0,0 @@
-/*
- * Copyright 2008-2011 the original author or authors.
- *
- * Licensed 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 com.nominanuda.web.htmlcomposer;
-
-import java.util.LinkedList;
-import java.util.List;
-
-import javax.xml.transform.sax.SAXResult;
-import javax.xml.transform.sax.TransformerHandler;
-
-import com.nominanuda.code.Nullable;
-import com.nominanuda.lang.InstanceFactory;
-import com.nominanuda.lang.Strings;
-import com.nominanuda.web.htmlcomposer.DomOp;
-import com.nominanuda.xml.SAXPipeline;
-import com.nominanuda.xml.SaxBuffer;
-import com.nominanuda.xml.SaxBuffer.SaxBit;
-import com.nominanuda.xml.SaxBuffer.StartElement;
-
-public class JQuerySaxMatcher {
- private final DomOp operation;
- private String selector;
- private SaxBuffer saxBuf;
-
- public JQuerySaxMatcher(DomManipulationStmt domManipulationStmt) {
- operation = domManipulationStmt.getOperation();
- selector = domManipulationStmt.getSelector();
- saxBuf = new SaxBuffer();
- new SAXPipeline()
- .add(new InstanceFactory<TransformerHandler>(new HtmlFragmentChecker()))
- .complete()
- .build(domManipulationStmt.getSaxBuffer(), new SAXResult(saxBuf))
- .run();
- }
-
- public int match(LinkedList<SaxBit> bits, int i) {
- SaxBit bit = bits.get(i);
- List<SaxBit> sbl = saxBuf.getBits();
- if(SaxBuffer.isStartElement(bit) && selector.startsWith(".") && operation == DomOp.prepend) {
- StartElement se = (StartElement)bit;
-// String cls = se.attrs.getValue("class");
- if(classMatches(se.attrs.getValue("class"), selector.substring(1))) {
- int added = 0;
- for(int j = sbl.size() - 1; j >= 0; j--) {
- SaxBit bb = clean(sbl.get(j));
- if(isRelevant(bb)) {
- bits.add(i+1, bb);
- added++;
- }
- }
- return i + added;
- }
- } else if(SaxBuffer.isStartElement(bit) && operation == DomOp.html) {
- StartElement se = (StartElement)bit;
- if(se.localName.equals(selector)) {
- int added = 0;
- for(int j = sbl.size() - 1; j >= 0; j--) {
- SaxBit bb = clean(sbl.get(j));
- if(isRelevant(bb)) {
- bits.add(i+1, bb);
- added++;
- }
- }
- return i + added;
- }
- }
- return i+1;
- }
-
- private boolean classMatches(@Nullable String clsAttr, String targetClass) {
- return clsAttr != null && Strings.splitAndTrim(clsAttr, "\\s+").contains(targetClass);
- }
-
- private SaxBit clean(SaxBit saxBit) {
- return saxBit;
- }
-
- private boolean isRelevant(SaxBit bb) {
-
- return ! (SaxBuffer.isStartDocument(bb)||SaxBuffer.isEndDocument(bb));
- }
-}
View
87 zen-webservice/src/test/java/com/nominanuda/web/htmlcomposer/HtmlSaxPageTest.java
@@ -0,0 +1,87 @@
+package com.nominanuda.web.htmlcomposer;
+
+import static com.nominanuda.web.htmlcomposer.DomOp.after;
+import static com.nominanuda.web.htmlcomposer.DomOp.append;
+import static com.nominanuda.web.htmlcomposer.DomOp.before;
+import static com.nominanuda.web.htmlcomposer.DomOp.html;
+import static com.nominanuda.web.htmlcomposer.DomOp.prepend;
+import static com.nominanuda.web.htmlcomposer.DomOp.replaceWith;
+import static org.junit.Assert.assertEquals;
+
+import java.io.CharArrayWriter;
+import java.io.InputStream;
+import java.io.StringReader;
+import java.util.LinkedList;
+
+import javax.xml.transform.Source;
+import javax.xml.transform.sax.SAXResult;
+import javax.xml.transform.sax.SAXSource;
+
+import nu.validator.htmlparser.sax.HtmlParser;
+
+import org.apache.log4j.BasicConfigurator;
+import org.junit.Test;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
+
+import com.nominanuda.io.ReaderInputStream;
+import com.nominanuda.lang.InstanceFactory;
+import com.nominanuda.lang.ObjectFactory;
+import com.nominanuda.web.http.HttpProtocol;
+import com.nominanuda.xml.HtmlFragmentParser;
+import com.nominanuda.xml.SAXPipeline;
+import com.nominanuda.xml.SaxBuffer;
+import com.nominanuda.xml.XHtml5Serializer;
+
+public class HtmlSaxPageTest implements HttpProtocol {
+ static {
+ BasicConfigurator.configure();
+ }
+ @Test
+ public void test() throws SAXException {
+ LinkedList<DomManipulationStmt> stmts = new LinkedList<DomManipulationStmt>();
+ stmts.add(new DomManipulationStmt("body", f("<div/>"), html));
+ stmts.add(new DomManipulationStmt("div", f("abc"), html));
+ stmts.add(new DomManipulationStmt("div", f("0<p>1</p>1.5<p>2</p>3"), replaceWith));
+ stmts.add(new DomManipulationStmt("p", f("BEFOREP"), before));
+ stmts.add(new DomManipulationStmt("p", f("AFTERP"), after));
+ stmts.add(new DomManipulationStmt("p", f("PREPENDP"), prepend));
+ stmts.add(new DomManipulationStmt("p", f("APPENDP"), append));
+ streamPage(stmts);
+ }
+
+ private void streamPage(Iterable<DomManipulationStmt> stmts)
+ throws SAXException {
+ HtmlSaxPage p = new HtmlSaxPage();
+ for(DomManipulationStmt stmt : stmts) {
+ p.applyStmt(stmt);
+ }
+ CharArrayWriter out = new CharArrayWriter();
+ XHtml5Serializer ser = new XHtml5Serializer(out);
+ new SaxBuffer.StartDocument().send(ser);
+ new SaxBuffer.StartElement(HTMLNS,"html","html",new AttributesImpl()).send(ser);
+ p.toSAX(ser);
+ new SaxBuffer.EndElement(HTMLNS,"html","html").send(ser);
+ new SaxBuffer.EndDocument().send(ser);
+ assertEquals("<html><head></head><body>0BEFOREP<p>PREPENDP1APPENDP</p>AFTERP1.5BEFOREP<p>PREPENDP2APPENDP</p>AFTERP3</body></html>", out.toString());
+ }
+
+ private ObjectFactory<SaxBuffer> f(String s) {
+ InputStream is = new ReaderInputStream(new StringReader(s), UTF_8);
+ SaxBuffer sbuf = new SaxBuffer();
+ new SAXPipeline()
+ .complete()
+ .build(saxSource(is), new SAXResult(sbuf))
+ .run();
+ return new InstanceFactory<SaxBuffer>(sbuf);
+ }
+
+ private Source saxSource(InputStream is) {
+ HtmlParser parser = new HtmlParser();
+ parser.setMappingLangToXmlLang(true);
+ parser.setReportingDoctype(false);
+ SAXSource src = new SAXSource(new HtmlFragmentParser(parser), new InputSource(is));
+ return src;
+ }
+}
Please sign in to comment.
Something went wrong with that request. Please try again.