1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package info.magnolia.cms.gui.dialog;
35
36 import info.magnolia.cms.core.NodeData;
37 import info.magnolia.cms.gui.control.Edit;
38 import info.magnolia.cms.gui.misc.CssConstants;
39 import info.magnolia.cms.util.BooleanUtil;
40
41 import java.io.IOException;
42 import java.io.Writer;
43 import java.util.HashMap;
44 import java.util.Map;
45
46 import javax.jcr.PropertyType;
47
48 import org.apache.commons.lang.StringUtils;
49 import org.slf4j.Logger;
50 import org.slf4j.LoggerFactory;
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70 public class DialogEditCode extends DialogBox {
71
72
73
74
75 private static final String ATTRIBUTE_CODEMIRROR_LOADED = "info.magnolia.cms.gui.dialog.codemirror.loaded";
76
77 private static final Logger log = LoggerFactory.getLogger(DialogEditCode.class);
78
79
80
81 public static final Map<String,String> availableParsers = new HashMap<String,String>();
82
83 static {
84 availableParsers.put("js", "JSParser");
85 availableParsers.put("javascript", "JSParser");
86 availableParsers.put("processedJs", "JSParser");
87 availableParsers.put("css", "CSSParser");
88 availableParsers.put("processedCss", "CSSParser");
89 availableParsers.put("html", "HTMLMixedParser");
90 availableParsers.put("freemarker", "FreemarkerParser");
91 availableParsers.put("ftl", "FreemarkerParser");
92 availableParsers.put("groovy", "GroovyParser");
93 availableParsers.put("generic", "HTMLMixedParser");
94 }
95
96
97
98
99 public void drawHtml(Writer out) throws IOException {
100 final Edit control = new Edit(this.getName(), this.getValue());
101 control.setType(this.getConfigValue("type", PropertyType.TYPENAME_STRING));
102 control.setCssClass(CssConstants.CSSCLASS_EDIT);
103 if (this.getConfigValue("saveInfo").equals("false")) {
104 control.setSaveInfo(false);
105 }
106
107 boolean useHighlighter = BooleanUtil.toBoolean(this.getConfigValue("useCodeHighlighter"), true);
108 log.debug("useHighlighter? {}",useHighlighter);
109 if(!useHighlighter){
110 drawSimpleEditor(out, control);
111 return;
112 }
113
114 final String language = this.getConfigValue("language");
115 String parser = null;
116 if(StringUtils.isNotBlank(language)){
117 parser = getAvailableParser(language.trim());
118 if(parser == null){
119 log.warn("no suitable parser found for language {}. No syntax highlighting will be available. Look at the documentation for the supported languages. ", language);
120 drawSimpleEditor(out, control);
121 return;
122 }
123 }
124 drawEditorWithSyntaxHighligher(out, control, parser);
125 }
126
127 private void drawSimpleEditor(Writer out, Edit control) throws IOException {
128 control.setRows(this.getConfigValue("rows", "1"));
129 control.setCssStyles("width", this.getConfigValue("width", "100%"));
130 control.setCssStyles("font-family", "Courier New, monospace");
131 control.setCssStyles("font-size", "14px");
132 if (this.getConfigValue("onchange", null) != null) {
133 control.setEvent("onchange", this.getConfigValue("onchange"));
134 }
135 this.drawHtmlPre(out);
136 out.write(control.getHtml());
137 this.drawHtmlPost(out);
138 }
139
140 private void drawEditorWithSyntaxHighligher(Writer out, Edit control, String parser) throws IOException{
141 final String pathToCodeMirror = this.getRequest().getContextPath() + "/.resources/js/codemirror/";
142 if(parser == null) {
143
144 final NodeData extNodeData = this.getStorageNode().getNodeData("extension");
145
146 if(extNodeData.isExist()){
147 final String ext = extNodeData.getString();
148 parser = getAvailableParser(ext);
149 } else {
150
151 final String template = this.getStorageNode().getMetaData().getTemplate();
152 parser = getAvailableParser(template);
153 }
154 if(parser == null){
155 log.debug("No suitable parser found. Falling back to generic.");
156 parser = getAvailableParser("generic");
157 }
158 }
159
160 control.setRows(this.getConfigValue("rows", "25"));
161 control.setRows(this.getConfigValue("cols", "100"));
162
163 this.drawHtmlPre(out);
164
165 if (getRequest().getAttribute(ATTRIBUTE_CODEMIRROR_LOADED) == null) {
166 out.write("<script type=\"text/javascript\" src=\""+ pathToCodeMirror + "codemirror-min.js\"></script>");
167 getRequest().setAttribute(ATTRIBUTE_CODEMIRROR_LOADED, true);
168 }
169
170 final StringBuilder inlineStyle = new StringBuilder("<style>\n");
171 inlineStyle.append(".CodeMirror-line-numbers {\n");
172 inlineStyle.append("background-color: #eee;\n");
173 inlineStyle.append("text-align: right;\n");
174 inlineStyle.append("font-family: monospace;\n");
175 inlineStyle.append("font-size: 10pt;\n");
176 inlineStyle.append("color: #aaa;\n");
177 inlineStyle.append("line-height: 16px;\n");
178 inlineStyle.append("padding: .4em;\n");
179 inlineStyle.append("width: 2.2em;\n");
180 inlineStyle.append("</style>\n");
181 out.write(inlineStyle.toString());
182
183 out.write("<div class=\"editorWrapper\" style=\"border: 1px solid #999; padding: 3px;\">");
184 out.write(control.getHtml());
185
186 final boolean lineNumbers = BooleanUtil.toBoolean(this.getConfigValue("lineNumbers"), true);
187 final boolean readOnly = BooleanUtil.toBoolean(this.getConfigValue("readOnly"), false);
188 final String editorVar = "editor"+this.getName();
189
190 out.write("\n<script>\n");
191 out.write("MgnlDHTMLUtil.addOnLoad(function(){\n");
192 String codeMirrorEditor = "var " + editorVar +" = CodeMirror.fromTextArea(\""+this.getName()+"\", {\n"+
193 " path: \"" + pathToCodeMirror + "\",\n" +
194 " textWrapping: false,\n" +
195 " height: \"420px\",\n" +
196 " basefiles: [\"codemirror-base.min.js\"],\n" +
197 " parserfile: [\"allinone.js\"],\n" +
198 " stylesheet: [\""+ pathToCodeMirror +"css/jscolors.css\",\""+ pathToCodeMirror +"css/csscolors.css\",\""+
199 pathToCodeMirror +"css/xmlcolors.css\",\""+ pathToCodeMirror +"css/freemarkercolors.css\",\""+ pathToCodeMirror +"css/groovycolors.css\"],\n" +
200 (lineNumbers ? " lineNumbers:true,\n":"") +
201 (readOnly ? " readOnly:true,\n":"") +
202 " initCallback:function(e){ \n"+
203 " e.setParser('"+ parser +"');\n"+
204 " e.focus();\n"+
205 " } \n"+
206 "});\n";
207
208 out.write(codeMirrorEditor);
209
210 out.write(" var b = document.getElementById('mgnlSaveButton');\n");
211 out.write(" var existingOnClick = b.onclick;\n");
212 out.write(" b.onclick=function(){\n");
213
214 out.write(" document.getElementById('cm_hidden_"+ this.getName() + "').value = " + editorVar + ".getCode();\n");
215 out.write(" existingOnClick.apply(this);\n");
216 out.write(" }\n});\n");
217 out.write("</script>\n");
218 out.write("<input type=\"hidden\" name=\"" + this.getName() + "\" id=\"cm_hidden_" + this.getName() + "\" />\n");
219 out.write("</div><!-- closing editorWrapper -->\n");
220
221 this.drawHtmlPost(out);
222 }
223
224 private String getAvailableParser(String language){
225 final String parser = availableParsers.get(language);
226 log.debug("language is {}, parser is {}", language, parser);
227 return parser;
228 }
229 }