Wiki-Quellcode von VelocityMacros

Zuletzt geändert von Daniel Herrmann am 2026/02/04 20:23

Zeige letzte Bearbeiter
1 {{velocity output="false"}}
2 #macro (ckeditor_convert $text $toHTML $fromHTML $stripHTMLEnvelope)
3 #set ($sourceSyntax = $request.sourceSyntax)
4 #if ("$!sourceSyntax" != '')
5 #set ($sourceSyntax = $services.rendering.resolveSyntax($sourceSyntax))
6 #end
7 #if (!$sourceSyntax)
8 #set ($sourceSyntax = $doc.syntax)
9 #end
10 #if ($toHTML)
11 #set ($source = {
12 'documentReference': $doc.documentReference,
13 'syntax': $sourceSyntax,
14 'restricted' : $request.wysiwygRestricted
15 })
16 #if ($fromHTML)
17 #set ($source.html = $text)
18 #else
19 #set ($source.content = $text)
20 #end
21 #if ($stripHTMLEnvelope)
22 ## Don't wrap the rendered content with the HTML and BODY tags. This is needed when the HTML fragment is injected
23 ## directly in the current page, e.g. when CKEditor is used in-line (no iframe). We still need to send back the
24 ## required style sheets and JavaScript files because some of them might not be available in the target page, e.g.
25 ## when a macro is inserted and it needs resource files not available on every page.
26 #template('display_macros.vm')
27 #initRequiredSkinExtensions()
28 #set ($output = "#ckeditor_getRenderedContent($source)$!html")
29 #sendRequiredSkinExtensions()
30 #else
31 ## Returns a full HTML page, including the HEAD tag with the style sheets and possibly the JavaScript includes.
32 ## This is needed when the edited content is loaded in an iframe, which is the case when CKEditor replaces a text
33 ## area (classical editor).
34 #set ($output = "#ckeditor_renderContentSheet($source)")
35 #end
36 #else
37 #set ($output = $services.wysiwyg.fromAnnotatedXHTML($text, $sourceSyntax.toIdString()))
38 #end
39 #if ("$!output" != '' || $output == '')
40 $output##
41 #else
42 ## The output is null so an exception must have been thrown.
43 $response.sendError(500)
44 #end
45 #end
46
47 #macro (ckeditor_renderContentSheet $source)
48 ## The $source variable is used inside the content sheet.
49 #set ($output = $services.wysiwyg.render('CKEditor.ContentSheet'))
50 ## Unescape {{ which happened in CKEditor.ContentSheet for protecting the {{html}} macro.
51 $!output.replace('{{', '{{')##
52 #end
53
54 #macro (ckeditor_getRenderedContent $source)
55 ## Make sure the edited content is rendered for view because this is a WYSIWYG editor.
56 #set ($macro.previousDisplayMode = $xcontext.displayMode)
57 #set ($discard = $xcontext.setDisplayMode('view'))
58 #set ($restricted = "$!source.restricted" == 'true')
59 #if ($source.html)
60 #set ($html = $services.wysiwyg.parseAndRender($source.html, $source.syntax, $source.documentReference, $restricted))
61 #else
62 #set ($html = $services.wysiwyg.toAnnotatedXHTML($source.content, $source.syntax, $source.documentReference, $restricted))
63 #end
64 #if ("$!html" == '')
65 ## Prevent Firefox from inserting bogus whitespace when the text area is empty.
66 ## CKEDITOR-185: Whitespace is generated in Firefox when creating a page without typing the content
67 #set ($html = '<p></p>')
68 #end
69 ## Restore the previous display mode.
70 #set ($discard = $xcontext.setDisplayMode($macro.previousDisplayMode))
71 #end
72
73 #macro (ckeditor_importCSS $groupId $artifactId $path $evaluate)
74 #set ($url = $services.webjars.url("$groupId:$artifactId", $path, {'evaluate': $evaluate}))
75 #set ($discard = $xwiki.linkx.use($url, {'type': 'text/css', 'rel': 'stylesheet'}))
76 #end
77
78 #macro (importCKEditorResources)
79 #set ($discard = $xwiki.ssx.use('CKEditor.EditSheet'))
80 ## Add the version of each JavaScript dependency of CKEditor Integration to the URL used to load the CKEditor in order
81 ## to make sure the browser cache is invalidated when one of these versions changes (e.g. when we upgrade XWiki or one
82 ## of these dependencies but the CKEditor version remains the same).
83 #set ($discard = $xwiki.jsx.use('CKEditor.EditSheet', {
84 'v': $services.extension.installed.getInstalledExtension('org.xwiki.platform:xwiki-platform-ckeditor-ui',
85 "wiki:$xcontext.database").version.value,
86 'xwiki-version': $services.extension.core.getCoreExtension(
87 'org.xwiki.platform:xwiki-platform-tree-webjar').version.value,
88 'fast-diff-version': $services.extension.installed.getInstalledExtension('org.webjars.npm:fast-diff',
89 "wiki:$xcontext.database").version.value,
90 'bs3typeahead-version': $services.extension.installed.getInstalledExtension('org.webjars.npm:bootstrap-3-typeahead',
91 "wiki:$xcontext.database").version.value
92 }))
93 #ckeditor_importCSS('org.xwiki.platform' 'xwiki-platform-ckeditor-plugins' 'webjar.bundle.min.css' true)
94 ## Tree styles needed for the document/attachment tree picker.
95 #set ($discard = $xwiki.linkx.use($services.webjars.url('org.xwiki.platform:xwiki-platform-tree-webjar', 'tree.min.css',
96 {'evaluate': true}), {'type': 'text/css', 'rel': 'stylesheet'}))
97 #set ($discard = $xwiki.linkx.use($services.webjars.url('org.xwiki.platform:xwiki-platform-tree-webjar',
98 'finder.min.css', {'evaluate': true}), {'type': 'text/css', 'rel': 'stylesheet'}))
99 #end
100
101 #macro (ckeditor $parameters)
102 #importCKEditorResources
103 ##
104 #set ($escapedName = $escapetool.xml($parameters.attributes.name))
105 <input value="$!escapedName" name="RequiresHTMLConversion" type="hidden"/>
106 ##
107 #set ($syntaxId = $parameters.attributes.get('data-syntax'))
108 <input value="$!escapetool.xml($syntaxId)" name="$!{escapedName}_syntax" type="hidden"/>
109 ##
110 ## Chrome doesn't cache the enabled/disabled state of the form fields so we must store this state in the value of
111 ## another form field. For instance, the enabled/disabled state of the RequiresHTMLConversion hidden input
112 ## determines which editor mode (WYSIWYG vs. Source) is loaded initially.
113 ## See CKEDITOR-34: Wiki syntax gets escaped when you click "Back" in the browser
114 <input value="" name="$!{escapedName}_cache" type="hidden" class="cache"/>
115 ##
116 #set ($discard = $parameters.attributes.putAll({
117 'class': "$!parameters.attributes.get('class') ckeditor-textarea loading",
118 'spellcheck': false
119 }))
120 ##
121 #set ($sourceDocumentReference = $parameters.attributes.get('data-sourceDocumentReference'))
122 #if (!$sourceDocumentReference)
123 #set ($sourceDocumentReference = $tdoc.documentReference)
124 #end
125 #set ($source = {
126 'documentReference': $sourceDocumentReference,
127 'syntax': $syntaxId,
128 'content': $parameters.content,
129 'restricted': $parameters.attributes.data-restricted
130 })
131 ##
132 ## Disable the file upload and drag & drop when the current user doesn't have edit right on the source document, if
133 ## the source is restricted. This is the case for instance when an user with comment right adds a comment to a page
134 ## they don't have edit right on. They are allowed to add the comment but they can't upload files because that
135 ## requires edit right. We check if the source is in restricted mode because in some cases (such as for Change Request
136 ## Application) we want to allow file upload even if the current user doesn't have edit right on the source document.
137 #if ($source.restricted == 'true' && !$services.security.authorization.hasAccess('edit', $source.documentReference))
138 #set ($parameters.attributes.data-upload-disabled = 'true')
139 #end
140 ## We use the velocity template context to convey the startupFocus parameter to CKEditor.
141 #if ($wysiwygEditorConfig.startupFocus)
142 #set ($parameters.attributes.data-startup-focus = 'true')
143 ## We make sure to clear this context so that it doesn't interfere with CKEditors opened later.
144 #set ($wysiwygEditorConfig.startupFocus = false)
145 #end
146 ##
147 <textarea
148 #foreach ($entry in $parameters.attributes.entrySet())
149 $entry.key="$!escapetool.xml($entry.value)"
150 #end
151 ## We render the content sheet at the end because the edited content can overwrite the variables used by this macro.
152 #set ($content = "#ckeditor_renderContentSheet($source)")
153 >$!escapetool.xml($content)</textarea>
154 #end
155
156 #macro (displayCKEditorConfigProperty $configDoc $propName $action)
157 <dt>
158 <label for="CKEditor.ConfigClass_$escapetool.xml($configDoc.getObject("CKEditor.ConfigClass").getNumber())_${propName}">$configDoc.displayPrettyName($propName)</label>
159 <span class="xHint">$escapetool.xml($services.localization.render("CKEditor.ConfigClass_${propName}.hint"))</span>
160 </dt>
161 <dd>#displayCKEditorConfigPropertyValue($configDoc $propName $action)</dd>
162 #end
163
164 #macro (displayCKEditorConfigBooleanProperty $configDoc $propName $action)
165 <dt>
166 <label>
167 #displayCKEditorConfigPropertyValue($configDoc $propName $action)
168 $configDoc.displayPrettyName($propName)
169 </label>
170 <span class="xHint">$escapetool.xml($services.localization.render("CKEditor.ConfigClass_${propName}.hint"))</span>
171 </dt>
172 <dd></dd>
173 #end
174
175 #macro (displayCKEditorConfigPropertyValue $configDoc $propName $action)
176 #unwrapXPropertyDisplay($configDoc.display($propName, $action))
177 #end
178
179 #macro (displayCKEditorConfig $configDoc $action)
180 #set ($discard = $xwiki.ssx.use('CKEditor.ConfigSheet'))
181 #set ($discard = $xwiki.jsx.use('CKEditor.ConfigSheet'))
182 #ckeditor_importCSS('org.webjars' 'bootstrap-select' 'css/bootstrap-select.min.css')
183 <dl class="ckeditor-config#if ($configDoc.isNew()) new#end">
184 #displayCKEditorConfigProperty($configDoc 'removePlugins' $action)
185 #displayCKEditorConfigProperty($configDoc 'removeButtons' $action)
186 #displayCKEditorConfigBooleanProperty($configDoc 'linkShowAdvancedTab' $action)
187 #displayCKEditorConfigBooleanProperty($configDoc 'linkShowTargetTab' $action)
188 #displayCKEditorConfigBooleanProperty($configDoc 'loadJavaScriptSkinExtensions' $action)
189 <dt>
190 <label>$configDoc.displayPrettyName('advanced')</label>
191 #set ($advancedHint = $escapetool.xml(
192 $services.localization.render('CKEditor.ConfigClass_advanced.hint', ['__linkStart__', '__linkEnd__'])
193 ).replace('__linkStart__', '<a href="http://docs.ckeditor.com/#!/api/CKEDITOR.config">'
194 ).replace('__linkEnd__', '</a>'))
195 <span class="xHint">$advancedHint</span>
196 </dt>
197 <dd>#displayCKEditorConfigPropertyValue($configDoc 'advanced' $action)</dd>
198 </dl>
199 #end
200
201 #**
202 * Deprecated. Use #initRequiredSkinExtensions() from display_macros.vm instead.
203 *#
204 #macro (ckeditor_initRequiredSkinExtensions)
205 #set ($requiredSkinExtensions = $collectiontool.orderedMap)
206 ## Save the import string for each skin extension plugin in order to be able to remove the always used extensions
207 ## (they are aready available on the edit page so there's no need to load them).
208 #foreach ($pluginName in ['ssrx', 'ssfx', 'ssx', 'linkx', 'jsrx', 'jsfx', 'jsx'])
209 #set ($discard = $requiredSkinExtensions.put($pluginName, $xwiki.get($pluginName).importString))
210 #end
211 #end
212
213 #**
214 * Deprecated. Use #getRequiredSkinExtensions() from display_macros.vm instead.
215 *#
216 #macro (ckeditor_getRequiredSkinExtensions)
217 #foreach ($entry in $requiredSkinExtensions.entrySet())
218 #set ($importString = $xwiki.get($entry.key).importString)
219 ## Remove the always used skin extensions, keep only those that have been requested by the macro parameter pickers.
220 $!stringtool.removeStart($importString, $entry.value).trim()##
221 #end
222 #end
223 {{/velocity}}