OLD | NEW |
1 // Copyright (C) 2007 Google Inc. | 1 // Copyright (C) 2007 Google Inc. |
2 // | 2 // |
3 // Licensed under the Apache License, Version 2.0 (the "License"); | 3 // Licensed under the Apache License, Version 2.0 (the "License"); |
4 // you may not use this file except in compliance with the License. | 4 // you may not use this file except in compliance with the License. |
5 // You may obtain a copy of the License at | 5 // You may obtain a copy of the License at |
6 // | 6 // |
7 // http://www.apache.org/licenses/LICENSE-2.0 | 7 // http://www.apache.org/licenses/LICENSE-2.0 |
8 // | 8 // |
9 // Unless required by applicable law or agreed to in writing, software | 9 // Unless required by applicable law or agreed to in writing, software |
10 // distributed under the License is distributed on an "AS IS" BASIS, | 10 // distributed under the License is distributed on an "AS IS" BASIS, |
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 // See the License for the specific language governing permissions and | 12 // See the License for the specific language governing permissions and |
13 // limitations under the License. | 13 // limitations under the License. |
14 | 14 |
15 package com.google.caja.plugin.stages; | 15 package com.google.caja.plugin.stages; |
16 | 16 |
17 import com.google.caja.lang.css.CssSchema; | 17 import com.google.caja.lang.css.CssSchema; |
18 import com.google.caja.lang.html.HtmlSchema; | 18 import com.google.caja.lang.html.HtmlSchema; |
19 import com.google.caja.lexer.FilePosition; | |
20 import com.google.caja.parser.AncestorChain; | 19 import com.google.caja.parser.AncestorChain; |
| 20 import com.google.caja.parser.css.CssTree; |
| 21 import com.google.caja.parser.html.DomParser; |
21 import com.google.caja.parser.js.Block; | 22 import com.google.caja.parser.js.Block; |
22 import com.google.caja.parser.js.Statement; | |
23 import com.google.caja.parser.js.TranslatedCode; | |
24 import com.google.caja.plugin.Dom; | 23 import com.google.caja.plugin.Dom; |
25 import com.google.caja.plugin.HtmlCompiler; | |
26 import com.google.caja.plugin.Job; | 24 import com.google.caja.plugin.Job; |
27 import com.google.caja.plugin.Jobs; | 25 import com.google.caja.plugin.Jobs; |
| 26 import com.google.caja.plugin.templates.TemplateCompiler; |
| 27 import com.google.caja.plugin.templates.TemplateSanitizer; |
| 28 import com.google.caja.reporting.MessageQueue; |
| 29 import com.google.caja.util.Pair; |
28 import com.google.caja.util.Pipeline; | 30 import com.google.caja.util.Pipeline; |
29 | 31 |
30 import java.util.ArrayList; | 32 import java.util.ArrayList; |
| 33 import java.util.Iterator; |
31 import java.util.List; | 34 import java.util.List; |
32 import java.util.ListIterator; | 35 import org.w3c.dom.Node; |
33 | 36 |
34 /** | 37 /** |
35 * Compile the html and add a method to the plugin for the | 38 * Compile the HTML and CSS to javascript. |
36 * html and one for each extracted script tag and event handler. | |
37 * | 39 * |
38 * @author mikesamuel@gmail.com | 40 * @author mikesamuel@gmail.com |
39 */ | 41 */ |
40 public final class CompileHtmlStage implements Pipeline.Stage<Jobs> { | 42 public final class CompileHtmlStage implements Pipeline.Stage<Jobs> { |
41 private final CssSchema cssSchema; | 43 private final CssSchema cssSchema; |
42 private final HtmlSchema htmlSchema; | 44 private final HtmlSchema htmlSchema; |
43 | 45 |
44 public CompileHtmlStage(CssSchema cssSchema, HtmlSchema htmlSchema) { | 46 public CompileHtmlStage(CssSchema cssSchema, HtmlSchema htmlSchema) { |
45 if (null == cssSchema) { throw new NullPointerException(); } | 47 if (null == cssSchema) { throw new NullPointerException(); } |
46 if (null == htmlSchema) { throw new NullPointerException(); } | 48 if (null == htmlSchema) { throw new NullPointerException(); } |
47 this.cssSchema = cssSchema; | 49 this.cssSchema = cssSchema; |
48 this.htmlSchema = htmlSchema; | 50 this.htmlSchema = htmlSchema; |
49 } | 51 } |
50 | 52 |
51 public boolean apply(Jobs jobs) { | 53 public boolean apply(Jobs jobs) { |
52 HtmlCompiler htmlc = new HtmlCompiler( | 54 List<Node> ihtmlRoots = new ArrayList<Node>(); |
53 cssSchema, htmlSchema, jobs.getMessageContext(), jobs.getMessageQueue(), | 55 List<CssTree.StyleSheet> stylesheets = new ArrayList<CssTree.StyleSheet>(); |
54 jobs.getPluginMeta()); | |
55 | 56 |
56 List<Statement> renderedHtmlStatements = new ArrayList<Statement>(); | 57 for (Iterator<Job> jobIt = jobs.getJobs().iterator(); jobIt.hasNext();) { |
57 | 58 Job job = jobIt.next(); |
58 ListIterator<Job> it = jobs.getJobs().listIterator(); | 59 switch (job.getType()) { |
59 while (it.hasNext()) { | 60 case HTML: |
60 Job job = it.next(); | 61 ihtmlRoots.add(job.getRoot().cast(Dom.class).node.getValue()); |
61 if (Job.JobType.HTML != job.getType()) { continue; } | 62 jobIt.remove(); |
62 | 63 break; |
63 it.remove(); | 64 case CSS: |
64 try { | 65 stylesheets.add(job.getRoot().cast(CssTree.StyleSheet.class).node); |
65 renderedHtmlStatements.add( | 66 jobIt.remove(); |
66 htmlc.compileDocument(((Dom) job.getRoot().node).getValue())); | 67 break; |
67 } catch (HtmlCompiler.BadContentException ex) { | 68 default: break; |
68 ex.toMessageQueue(jobs.getMessageQueue()); | |
69 } | 69 } |
70 } | 70 } |
71 | 71 |
72 if (!htmlc.getEventHandlers().isEmpty()) { | 72 MessageQueue mq = jobs.getMessageQueue(); |
73 TranslatedCode compiledHtml = new TranslatedCode(new Block( | 73 |
74 FilePosition.UNKNOWN, | 74 TemplateSanitizer ts = new TemplateSanitizer(htmlSchema, mq); |
75 new ArrayList<Statement>(htmlc.getEventHandlers()))); | 75 for (Node ihtmlRoot : ihtmlRoots) { ts.sanitize(ihtmlRoot); } |
76 jobs.getJobs().add(new Job(AncestorChain.instance(compiledHtml))); | 76 TemplateCompiler tc = new TemplateCompiler( |
| 77 ihtmlRoots, stylesheets, cssSchema, htmlSchema, |
| 78 jobs.getPluginMeta(), jobs.getMessageContext(), mq); |
| 79 tc.inspect(); |
| 80 Pair<Node, List<Block>> htmlAndJs = tc.getSafeHtml( |
| 81 DomParser.makeDocument(null, null)); |
| 82 |
| 83 jobs.getJobs().add(new Job(AncestorChain.instance(new Dom(htmlAndJs.a)))); |
| 84 for (Block bl : htmlAndJs.b) { |
| 85 jobs.getJobs().add(new Job(AncestorChain.instance(bl))); |
77 } | 86 } |
78 | 87 |
79 if (!renderedHtmlStatements.isEmpty()) { | |
80 Block htmlGeneration; | |
81 if (renderedHtmlStatements.size() == 1 | |
82 && renderedHtmlStatements.get(0) instanceof Block) { | |
83 htmlGeneration = (Block) renderedHtmlStatements.get(0); | |
84 } else { | |
85 htmlGeneration = new Block( | |
86 FilePosition.UNKNOWN, renderedHtmlStatements); | |
87 } | |
88 jobs.getJobs().add(new Job(AncestorChain.instance(htmlGeneration))); | |
89 } | |
90 return jobs.hasNoFatalErrors(); | 88 return jobs.hasNoFatalErrors(); |
91 } | 89 } |
92 } | 90 } |
OLD | NEW |