Änderungen von Dokument MentionsMacro
Zuletzt geändert von xwikiadmin am 2024/01/25 22:10
Von Version 1.1
bearbeitet von xwikiadmin
am 2020/07/08 22:24
am 2020/07/08 22:24
Änderungskommentar:
Install extension [org.xwiki.platform:xwiki-platform-mentions-ui/12.5.1]
Auf Version 10.1
bearbeitet von xwikiadmin
am 2023/02/06 13:37
am 2023/02/06 13:37
Änderungskommentar:
Install extension [org.xwiki.platform:xwiki-platform-mentions-ui/14.10.4]
Zusammenfassung
-
Objekte (3 geändert, 1 hinzugefügt, 0 gelöscht)
Details
- XWiki.JavaScriptExtension[0]
-
- Code
-
... ... @@ -1,57 +1,37 @@ 1 1 require.config({ 2 2 paths: { 3 - 'xwiki-suggestUsers': "$xwiki.getSkinFile('uicomponents/suggest/suggestUsersAndGroups.js', true))" + 4 - "?v=$escapetool.url($xwiki.version)" 3 + 'xwiki-suggestUsers': $jsontool.serialize($xwiki.getSkinFile('uicomponents/suggest/suggestUsersAndGroups.js')) 5 5 } 6 6 }); 7 7 require(['deferred!ckeditor', 'xwiki-suggestUsers', 'jquery', 'xwiki-meta'], function (ckeditorPromise, suggestUsers, $, xm) { 8 - /* 9 - * Keep records of the added anchors during the current edit session. 10 - * Note that the anchors saved here are not only the ones added on the current session, 11 - * but also those already present in the document. 12 - * For more information, see #getAnchor. 13 - * The information are stored on the form: 14 - * { reference: Array<String> } 15 - */ 16 - const anchorIds = {}; 17 - 7 + 18 18 /** 19 19 * Get the current wiki scope for displaying global, local or global and local users 20 20 */ 21 21 const userScope = "$!services.wiki.user.userScope"; 22 - 12 + 13 + // see https://stackoverflow.com/a/6248722/657524 14 + function random6chars() { 15 + // I generate the UID from two parts here 16 + // to ensure the random number provide enough bits. 17 + var firstPart = (Math.random() * 46656) | 0; 18 + var secondPart = (Math.random() * 46656) | 0; 19 + firstPart = ("000" + firstPart.toString(36)).slice(-3); 20 + secondPart = ("000" + secondPart.toString(36)).slice(-3); 21 + return firstPart + secondPart; 22 + } 23 + 23 23 /** 24 24 * Compute a new unique anchor for the given reference. 25 - * The uniquen ess oftheanchorisgivenbytwomechanisms:26 - * - retrieve on firstcallall mentions available oncurrentdocument and store them27 - * - thenuse that information tocomputeanext anchornotoverlappinganexistingone onthecurrentdocument.28 - * Themechanism isobviouslynot perfectand might beimproved laterbut shouldbenough for mostusage.26 + * The unique anchor is based on the mentionned user id, concatenaed with a random string of 6 alphanumeric 27 + * characters. 28 + * The chances of collision are quite low, about 46k mentions for a given mentioned user on a given page (assuming 29 + * that no mentions are ever deleted). 29 29 */ 30 30 const getAnchor = function (reference) { 31 - var existingIds; 32 - 33 - if (anchorIds.hasOwnProperty(reference)) { 34 - existingIds = anchorIds[reference]; 35 - } else { 36 - existingIds = []; 37 - $('.xwiki-mention').each(function() { 38 - var mention = $(this); 39 - if (mention.attr('data-reference') === reference) { 40 - existingIds.push(mention.attr('id')); 41 - } 42 - }); 43 - anchorIds[reference] = existingIds; 44 - } 45 - 46 - var counter = existingIds.length + 1; 47 - var refId = reference.replace(/[.:]/g, '-'); 48 - var proposedAnchor = refId + "-" + counter; 49 - while (existingIds.indexOf(proposedAnchor) != -1) { 50 - counter++; 51 - proposedAnchor = refId + "-" + counter; 52 - } 53 - anchorIds[reference].push(proposedAnchor); 54 - return proposedAnchor; 32 + const refId = reference.replace(/[.:]/g, '-'); 33 + const randomId = random6chars(); 34 + return refId + '-' + randomId; 55 55 }; 56 56 57 57 const search = function (text, callback) { ... ... @@ -59,8 +59,8 @@ 59 59 'input': text, 60 60 'limit': 6, 61 61 }; 62 - $.when(suggestUsers.loadUsers(userScope, params)).then(function (user){63 - const cct = user.map(function (x) { 42 + suggestUsers.loadUsers(userScope, params).then(users => { 43 + const cct = users.map(function (x) { 64 64 // insert an id because that's required by the mentions plugins. 65 65 x.id = x.value; 66 66 // Make sure to display the icon avatar or the image one. ... ... @@ -76,11 +76,11 @@ 76 76 return x; 77 77 }); 78 78 callback(cct); 79 - }) 59 + }); 80 80 } 81 81 82 - ckeditorPromise. done(function(ckeditor){83 - function confMentions(name) {62 + ckeditorPromise.then(ckeditor => { 63 + function getUserMentionsConfig(editor) { 84 84 return { 85 85 feed: function (opts, callback) { 86 86 search(opts.query, callback); ... ... @@ -88,33 +88,25 @@ 88 88 marker: '@', 89 89 minChars: 0, 90 90 itemsLimit: 6, 91 - itemTemplate: '<li data-id="{id}" class="ckeditor-autocomplete-item">'+ 92 - '<div>'+ 93 - '<span class="ckeditor-autocomplete-item-icon-wrapper">'+ 94 - '<span class="{cssClass}"></span>'+ 95 - '<img src="{imgUrl}" class="{imgClass}"/>'+ 96 - '</span>'+ 97 - '<span class="ckeditor-autocomplete-item-label">{label}</span>'+ 98 - '</div>'+ 99 - '</li>', 71 + itemTemplate: 72 + `<li data-id="{id}" class="ckeditor-autocomplete-item"> 73 + <div> 74 + <span class="ckeditor-autocomplete-item-icon-wrapper"> 75 + <span class="{cssClass}"></span> 76 + <img src="{imgUrl}" class="{imgClass}"/> 77 + </span> 78 + <span class="ckeditor-autocomplete-item-label">{label}</span> 79 + </div> 80 + </li>`, 100 100 outputTemplate: function (param) { 101 - var editor = ckeditor.instances[name]; 102 - var currentWikiReference = xm.documentReference.extractReference(XWiki.EntityType.WIKI); 103 - 104 - // Compute an absolute reference containing the wiki reference even if the user is local. 105 - var documentReference = XWiki.Model.resolve(param.id, XWiki.EntityType.DOCUMENT); 106 - if (!documentReference.extractReference(XWiki.EntityType.WIKI)) { 107 - documentReference = documentReference.appendParent(currentWikiReference); 108 - } 109 - var serializedReference = XWiki.Model.serialize(documentReference); 110 - editor.once('afterInsertHtml', function () { 82 + editor.once('afterInsertHtml', function() { 111 111 editor.execCommand('xwiki-macro-insert', { 112 112 name: 'mention', 113 - inline: true,85 + inline: 'enforce', 114 114 parameters: { 115 - reference: serializedReference,87 + reference: param.id, 116 116 style: 'FULL_NAME', 117 - anchor: getAnchor( serializedReference)89 + anchor: getAnchor(param.id) 118 118 } 119 119 }); 120 120 }); ... ... @@ -125,22 +125,19 @@ 125 125 }; 126 126 } 127 127 128 - function updateConf(config, name) { 129 - const newConf = config; 130 - newConf.mentions = newConf.mentions || []; 131 - newConf.mentions.push(confMentions(name)); 132 - return newConf; 100 + function updateConfig(editor) { 101 + editor.config.mentions = editor.config.mentions || []; 102 + editor.config.mentions.push(getUserMentionsConfig(editor)); 133 133 } 134 134 135 - var oldReplace = ckeditor.replace;136 - ckeditor.replace=function(element,config){137 - returnoldReplace.call(this,element,updateConf(config,element.id));138 - };139 - 140 - varoldInline=ckeditor.inline;141 - ckeditor.inline=functionlement, config){142 - return oldInline.call(this, element, updateConf(config, element.id));143 - }; 105 + ckeditor.on('instanceCreated', function(event) { 106 + // The editor instance was created but it not yet initialized. Unfortunately the configuration object passed when 107 + // the instance was created has not been merged with the global configuration yet. 108 + event.editor.once('configLoaded', function(event) { 109 + // The editor configuration has been loaded (the instance configuration has been merged with the global 110 + // configuration) but the editor has not been fully initialized yet so we can modify the configuration. 111 + updateConfig(event.editor); 112 + }); 113 + }); 144 144 }); 145 145 }); 146 -
- XWiki.StyleSheetExtension[0]
-
- Code
-
... ... @@ -11,3 +11,7 @@ 11 11 .xwiki-mention.removed { 12 12 text-decoration: line-through; 13 13 } 14 + 15 +blockquote.mention-quote { 16 + font-size: inherit; 17 +}
- XWiki.WikiMacroClass[0]
-
- Makro-Code
-
... ... @@ -1,26 +1,18 @@ 1 1 {{velocity}} 2 2 #set ($reference = $wikimacro.parameters.reference) 3 3 #set ($style = $wikimacro.parameters.style) 4 +#set ($type = "$!wikimacro.parameters.type") 5 +#set ($content = $services.mentions.format($reference.reference, $style, $type)) 4 4 #set ($anchor = $wikimacro.parameters.anchor) 5 -#set ($userProperties = $services.user.getProperties($reference)) 6 -#set ($firstName = $userProperties.getFirstName()) 7 -#set ($lastName = $userProperties.getLastName()) 8 -#set ($isCurrentUser = $xcontext.userReference == $reference.reference) 7 +#set ($isCurrentUser = $xcontext.userReference == $reference.reference && ($type == '' || $type == 'user')) 9 9 #set ($cssClasses = ['xwiki-mention', 'user']) 10 10 #if ($isCurrentUser) 11 11 #set ($discard = $cssClasses.add('self')) 12 12 #end 13 -#if ("$!firstName" == "") 14 - #set($content = "@$reference.reference.name") 15 -#elseif ($style == 'FIRST_NAME') 16 - #set($content = "@$firstName") 17 -#elseif ($style == 'LOGIN') 18 - #set($content = "@$reference.reference.name") 19 -#else 20 - #set($content = "@$firstName $!lastName") 21 -#end 22 22 #set ($link = $xwiki.getURL($reference.reference, 'view')) 23 23 {{html}} 24 -<a id="$anchor" class="$stringtool.join($cssClasses, ' ')" data-reference="$services.model.serialize($reference.reference, 'default')" href="$link">$content</a> 14 +<a id="$escapetool.xml($anchor)" class="$stringtool.join($cssClasses, ' ')" data-reference="$escapetool.xml($services.model.serialize($reference.reference, 'default'))" href="$escapetool.xml($link)">## 15 + $escapetool.xml($content)## Do not remove this comment as it ensures that the spacing after mention is not broken. 16 +</a> 25 25 {{/html}} 26 26 {{/velocity}} - Default categories
-
... ... @@ -1,0 +1,1 @@ 1 +Notifications - Makrobeschreibung
-
... ... @@ -1,1 +1,1 @@ 1 -Insert a user mention. 1 +Inserts a user mention.
- XWiki.WikiMacroParameterClass[3]
-
- Parameter-Beschreibung
-
... ... @@ -1,0 +1,1 @@ 1 +The type of mentioned actor. - Parameter-Name
-
... ... @@ -1,0 +1,1 @@ 1 +type - Parameter-Typ
-
... ... @@ -1,0 +1,1 @@ 1 +java.lang.String