Code source wiki de VelocityMacros
Version 2.1 par Florent Charton le 2024/08/08 18:44
Afficher les derniers auteurs
| author | version | line-number | content |
|---|---|---|---|
| 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 | #ckeditor_initRequiredSkinExtensions() | ||
| 27 | #set ($output = "#ckeditor_getRenderedContent($source)$!html") | ||
| 28 | #set ($discard = $response.setHeader('X-XWIKI-HTML-HEAD', "#ckeditor_getRequiredSkinExtensions()")) | ||
| 29 | #else | ||
| 30 | ## Returns a full HTML page, including the HEAD tag with the style sheets and possibly the JavaScript includes. | ||
| 31 | ## This is needed when the edited content is loaded in an iframe, which is the case when CKEditor replaces a text | ||
| 32 | ## area (classical editor). | ||
| 33 | #set ($output = "#ckeditor_renderContentSheet($source)") | ||
| 34 | #end | ||
| 35 | #else | ||
| 36 | #set ($output = $services.wysiwyg.fromAnnotatedXHTML($text, $sourceSyntax.toIdString())) | ||
| 37 | #if ("$!output" == '' && $output != '') | ||
| 38 | ## $output is null, probably because $services.wysiwyg.fromAnnotatedXHTML() is not available (before 10.10RC1) | ||
| 39 | #set ($xdom = $services.rendering.parse($text, 'xhtml/1.0')) | ||
| 40 | #set ($output = $services.rendering.render($xdom, $sourceSyntax.toIdString())) | ||
| 41 | #end | ||
| 42 | #end | ||
| 43 | #if ("$!output" != '' || $output == '') | ||
| 44 | $output## | ||
| 45 | #else | ||
| 46 | ## The output is null so an exception must have been thrown. | ||
| 47 | $response.sendError(500) | ||
| 48 | #end | ||
| 49 | #end | ||
| 50 | |||
| 51 | #macro (ckeditor_renderContentSheet $source) | ||
| 52 | ## The $source variable is used inside the content sheet. | ||
| 53 | #set ($output = $services.wysiwyg.render('CKEditor.ContentSheet')) | ||
| 54 | #if ("$!output" == '' && $output != '') | ||
| 55 | ## $output is null, probably because $services.wysiwyg.render() is not available (before 7.4.1) | ||
| 56 | #set ($output = $xwiki.getDocument('CKEditor.ContentSheet').getRenderedContent()) | ||
| 57 | #set ($skinExtensionHooks = { | ||
| 58 | 'ssx': 'CssSkinExtensionPlugin', | ||
| 59 | 'ssfx': 'CssSkinFileExtensionPlugin', | ||
| 60 | 'ssrx': 'CssResourceSkinExtensionPlugin' | ||
| 61 | }) | ||
| 62 | #foreach ($entry in $skinExtensionHooks.entrySet()) | ||
| 63 | #set ($output = $output.replace("<!-- com.xpn.xwiki.plugin.skinx.$entry.value -->", | ||
| 64 | $xwiki.get($entry.key).importString)) | ||
| 65 | #end | ||
| 66 | #end | ||
| 67 | ## Unescape {{ which happened in CKEditor.ContentSheet for protecting the {{html}} macro. | ||
| 68 | $!output.replace('&#123;&#123;', '{{')## | ||
| 69 | #end | ||
| 70 | |||
| 71 | #macro (ckeditor_getRenderedContent $source) | ||
| 72 | ## Make sure the edited content is rendered for view because this is a WYSIWYG editor. | ||
| 73 | #set ($macro.previousDisplayMode = $xcontext.displayMode) | ||
| 74 | #set ($discard = $xcontext.setDisplayMode('view')) | ||
| 75 | #if ($xcontext.displayMode != 'view') | ||
| 76 | ## Before XWiki 14.0-rc-1, 13.4.7, 13.10.3 and 12.10.12 there's no API to get the current display mode so we can't | ||
| 77 | ## restore the previous display mode properly. We assume the previous display mode is 'edit' because the WYSIWYG | ||
| 78 | ## editor is used. | ||
| 79 | #set ($macro.previousDisplayMode = 'edit') | ||
| 80 | #end | ||
| 81 | #set ($restricted = "$!source.restricted" == 'true') | ||
| 82 | #if ($source.html) | ||
| 83 | #set ($html = $services.wysiwyg.parseAndRender($source.html, $source.syntax, $source.documentReference, $restricted)) | ||
| 84 | #if ("$!html" == '' && $html != '') | ||
| 85 | ## Before XWiki 11.9RC1 (see XWIKI-16737) | ||
| 86 | #set ($html = $services.wysiwyg.parseAndRender($source.html, $source.syntax.toIdString())) | ||
| 87 | #end | ||
| 88 | #else | ||
| 89 | #set ($html = $services.wysiwyg.toAnnotatedXHTML($source.content, $source.syntax, $source.documentReference, $restricted)) | ||
| 90 | #if ("$!html" == '' && $html != '') | ||
| 91 | ## Before XWiki 11.9RC1 (see XWIKI-16737) | ||
| 92 | #set ($html = $services.wysiwyg.toAnnotatedXHTML($source.content, $source.syntax.toIdString())) | ||
| 93 | #end | ||
| 94 | #end | ||
| 95 | #if ("$!html" == '') | ||
| 96 | ## Prevent Firefox from inserting bogus whitespace when the text area is empty. | ||
| 97 | ## CKEDITOR-185: Whitespace is generated in Firefox when creating a page without typing the content | ||
| 98 | #set ($html = '<p></p>') | ||
| 99 | #end | ||
| 100 | ## Restore the previous display mode. | ||
| 101 | #set ($discard = $xcontext.setDisplayMode($macro.previousDisplayMode)) | ||
| 102 | #end | ||
| 103 | |||
| 104 | #macro (ckeditor_importCSS $groupId $artifactId $path $evaluate) | ||
| 105 | #set ($url = $services.webjars.url("$groupId:$artifactId", $path, {'evaluate': $evaluate})) | ||
| 106 | #set ($discard = $xwiki.linkx.use($url, {'type': 'text/css', 'rel': 'stylesheet'})) | ||
| 107 | #end | ||
| 108 | |||
| 109 | #macro (importCKEditorResources) | ||
| 110 | #set ($discard = $xwiki.ssx.use('CKEditor.EditSheet')) | ||
| 111 | ## Add the version of each JavaScript dependency of CKEditor Integration to the URL used to load the CKEditor in order | ||
| 112 | ## to make sure the browser cache is invalidated when one of these versions changes (e.g. when we upgrade XWiki or one | ||
| 113 | ## of these dependencies but the CKEditor version remains the same). | ||
| 114 | #set ($discard = $xwiki.jsx.use('CKEditor.EditSheet', { | ||
| 115 | 'v': $services.extension.installed.getInstalledExtension('org.xwiki.platform:xwiki-platform-ckeditor-ui', | ||
| 116 | "wiki:$xcontext.database").version.value, | ||
| 117 | 'xwiki-version': $services.extension.core.getCoreExtension( | ||
| 118 | 'org.xwiki.platform:xwiki-platform-tree-webjar').version.value, | ||
| 119 | 'fast-diff-version': $services.extension.installed.getInstalledExtension('org.webjars.npm:fast-diff', | ||
| 120 | "wiki:$xcontext.database").version.value, | ||
| 121 | 'bs3typeahead-version': $services.extension.installed.getInstalledExtension('org.webjars.npm:bootstrap-3-typeahead', | ||
| 122 | "wiki:$xcontext.database").version.value | ||
| 123 | })) | ||
| 124 | #ckeditor_importCSS('org.xwiki.platform' 'xwiki-platform-ckeditor-plugins' 'webjar.bundle.min.css' true) | ||
| 125 | ## Tree styles needed for the document/attachment tree picker. | ||
| 126 | #set ($discard = $xwiki.linkx.use($services.webjars.url('org.xwiki.platform:xwiki-platform-tree-webjar', 'tree.min.css', | ||
| 127 | {'evaluate': true}), {'type': 'text/css', 'rel': 'stylesheet'})) | ||
| 128 | #set ($discard = $xwiki.linkx.use($services.webjars.url('org.xwiki.platform:xwiki-platform-tree-webjar', | ||
| 129 | 'finder.min.css', {'evaluate': true}), {'type': 'text/css', 'rel': 'stylesheet'})) | ||
| 130 | #end | ||
| 131 | |||
| 132 | #macro (ckeditor $parameters) | ||
| 133 | #importCKEditorResources | ||
| 134 | ## | ||
| 135 | #set ($escapedName = $escapetool.xml($parameters.attributes.name)) | ||
| 136 | <input value="$!escapedName" name="RequiresHTMLConversion" type="hidden"/> | ||
| 137 | ## | ||
| 138 | #set ($syntaxId = $parameters.attributes.get('data-syntax')) | ||
| 139 | <input value="$!escapetool.xml($syntaxId)" name="$!{escapedName}_syntax" type="hidden"/> | ||
| 140 | ## | ||
| 141 | ## Chrome doesn't cache the enabled/disabled state of the form fields so we must store this state in the value of | ||
| 142 | ## another form field. For instance, the enabled/disabled state of the RequiresHTMLConversion hidden input | ||
| 143 | ## determines which editor mode (WYSIWYG vs. Source) is loaded initially. | ||
| 144 | ## See CKEDITOR-34: Wiki syntax gets escaped when you click "Back" in the browser | ||
| 145 | <input value="" name="$!{escapedName}_cache" type="hidden" class="cache"/> | ||
| 146 | ## | ||
| 147 | #set ($discard = $parameters.attributes.putAll({ | ||
| 148 | 'class': "$!parameters.attributes.get('class') ckeditor-textarea loading", | ||
| 149 | 'spellcheck': false | ||
| 150 | })) | ||
| 151 | ## | ||
| 152 | #set ($sourceDocumentReference = $parameters.attributes.get('data-sourceDocumentReference')) | ||
| 153 | #if (!$sourceDocumentReference) | ||
| 154 | #set ($sourceDocumentReference = $tdoc.documentReference) | ||
| 155 | #end | ||
| 156 | #set ($source = { | ||
| 157 | 'documentReference': $sourceDocumentReference, | ||
| 158 | 'syntax': $syntaxId, | ||
| 159 | 'content': $parameters.content, | ||
| 160 | 'restricted': $parameters.attributes.data-restricted | ||
| 161 | }) | ||
| 162 | ## | ||
| 163 | ## Disable the file upload and drag & drop when the current user doesn't have edit right on the source document, if | ||
| 164 | ## the source is restricted. This is the case for instance when an user with comment right adds a comment to a page | ||
| 165 | ## they don't have edit right on. They are allowed to add the comment but they can't upload files because that | ||
| 166 | ## requires edit right. We check if the source is in restricted mode because in some cases (such as for Change Request | ||
| 167 | ## Application) we want to allow file upload even if the current user doesn't have edit right on the source document. | ||
| 168 | #if ($source.restricted == 'true' && !$services.security.authorization.hasAccess('edit', $source.documentReference)) | ||
| 169 | #set ($parameters.attributes.data-upload-disabled = 'true') | ||
| 170 | #end | ||
| 171 | ## | ||
| 172 | <textarea | ||
| 173 | #foreach ($entry in $parameters.attributes.entrySet()) | ||
| 174 | $entry.key="$!escapetool.xml($entry.value)" | ||
| 175 | #end | ||
| 176 | ## We render the content sheet at the end because the edited content can overwrite the variables used by this macro. | ||
| 177 | #set ($content = "#ckeditor_renderContentSheet($source)") | ||
| 178 | >$!escapetool.xml($content)</textarea> | ||
| 179 | #end | ||
| 180 | |||
| 181 | #macro (displayCKEditorConfigProperty $configDoc $propName $action) | ||
| 182 | <dt> | ||
| 183 | <label>$configDoc.displayPrettyName($propName)</label> | ||
| 184 | <span class="xHint">$escapetool.xml($services.localization.render("CKEditor.ConfigClass_${propName}.hint"))</span> | ||
| 185 | </dt> | ||
| 186 | <dd>#displayCKEditorConfigPropertyValue($configDoc $propName $action)</dd> | ||
| 187 | #end | ||
| 188 | |||
| 189 | #macro (displayCKEditorConfigBooleanProperty $configDoc $propName $action) | ||
| 190 | <dt> | ||
| 191 | <label> | ||
| 192 | #displayCKEditorConfigPropertyValue($configDoc $propName $action) | ||
| 193 | $configDoc.displayPrettyName($propName) | ||
| 194 | </label> | ||
| 195 | <span class="xHint">$escapetool.xml($services.localization.render("CKEditor.ConfigClass_${propName}.hint"))</span> | ||
| 196 | </dt> | ||
| 197 | <dd></dd> | ||
| 198 | #end | ||
| 199 | |||
| 200 | #macro (displayCKEditorConfigPropertyValue $configDoc $propName $action) | ||
| 201 | #unwrapXPropertyDisplay($configDoc.display($propName, $action)) | ||
| 202 | #end | ||
| 203 | |||
| 204 | #macro (displayCKEditorConfig $configDoc $action) | ||
| 205 | #set ($discard = $xwiki.ssx.use('CKEditor.ConfigSheet')) | ||
| 206 | #set ($discard = $xwiki.jsx.use('CKEditor.ConfigSheet')) | ||
| 207 | #ckeditor_importCSS('org.webjars' 'bootstrap-select' 'css/bootstrap-select.min.css') | ||
| 208 | <dl class="ckeditor-config#if ($configDoc.isNew()) new#end"> | ||
| 209 | #displayCKEditorConfigProperty($configDoc 'removePlugins' $action) | ||
| 210 | #displayCKEditorConfigProperty($configDoc 'removeButtons' $action) | ||
| 211 | #displayCKEditorConfigBooleanProperty($configDoc 'linkShowAdvancedTab' $action) | ||
| 212 | #displayCKEditorConfigBooleanProperty($configDoc 'linkShowTargetTab' $action) | ||
| 213 | #displayCKEditorConfigBooleanProperty($configDoc 'loadJavaScriptSkinExtensions' $action) | ||
| 214 | <dt> | ||
| 215 | <label>$configDoc.displayPrettyName('advanced')</label> | ||
| 216 | #set ($advancedHint = $escapetool.xml( | ||
| 217 | $services.localization.render('CKEditor.ConfigClass_advanced.hint', ['__linkStart__', '__linkEnd__']) | ||
| 218 | ).replace('__linkStart__', '<a href="http://docs.ckeditor.com/#!/api/CKEDITOR.config">' | ||
| 219 | ).replace('__linkEnd__', '</a>')) | ||
| 220 | <span class="xHint">$advancedHint</span> | ||
| 221 | </dt> | ||
| 222 | <dd>#displayCKEditorConfigPropertyValue($configDoc 'advanced' $action)</dd> | ||
| 223 | </dl> | ||
| 224 | #end | ||
| 225 | |||
| 226 | #macro (ckeditor_initRequiredSkinExtensions) | ||
| 227 | #set ($requiredSkinExtensions = $collectiontool.orderedMap) | ||
| 228 | #if ("$!requiredSkinExtensions" == '') | ||
| 229 | ## For XWiki versions older than 12.1RC1 fallback on the old $collectionstool (available since 4.0M1). | ||
| 230 | #set ($requiredSkinExtensions = $collectionstool.orderedMap) | ||
| 231 | #end | ||
| 232 | ## Save the import string for each skin extension plugin in order to be able to remove the always used extensions | ||
| 233 | ## (they are aready available on the edit page so there's no need to load them). | ||
| 234 | #foreach ($pluginName in ['ssrx', 'ssfx', 'ssx', 'linkx', 'jsrx', 'jsfx', 'jsx']) | ||
| 235 | #set ($discard = $requiredSkinExtensions.put($pluginName, $xwiki.get($pluginName).importString)) | ||
| 236 | #end | ||
| 237 | #end | ||
| 238 | |||
| 239 | #macro (ckeditor_getRequiredSkinExtensions) | ||
| 240 | #foreach ($entry in $requiredSkinExtensions.entrySet()) | ||
| 241 | #set ($importString = $xwiki.get($entry.key).importString) | ||
| 242 | ## Remove the always used skin extensions, keep only those that have been requested by the macro parameter pickers. | ||
| 243 | $!stringtool.removeStart($importString, $entry.value).trim()## | ||
| 244 | #end | ||
| 245 | #end | ||
| 246 | |||
| 247 | #macro (ckeditor_defineSortTool $sortToolVariable) | ||
| 248 | #set ($checkedExtension = "org.xwiki.commons:xwiki-commons-velocity") | ||
| 249 | ## Because of an API collision, $collectionstool has been replaced by $collectiontool in XCOMMONS-1861 | ||
| 250 | #if ($services.extension.core.getCoreExtension($checkedExtension).id.version.compareTo("12.1-SNAPSHOT") >= 0) | ||
| 251 | #setVariable ($sortToolVariable, $collectiontool) | ||
| 252 | ## With the upgrade of Velocity $sorttool has been replaced by $collectionstool (XCOMMONS-1296) | ||
| 253 | #elseif ($services.extension.core.getCoreExtension($checkedExtension).id.version.compareTo("12.0-SNAPSHOT") >= 0) | ||
| 254 | #setVariable ($sortToolVariable, $collectionstool) | ||
| 255 | ## Old API for sorting was $sorttool | ||
| 256 | #else | ||
| 257 | #setVariable ($sortToolVariable, $sorttool) | ||
| 258 | #end | ||
| 259 | #end | ||
| 260 | |||
| 261 | #ckeditor_defineSortTool("$resolvedSortTool") | ||
| 262 | {{/velocity}} |