');n.append(s);var i=function(){return $('.PostStream-item[data-id="'+r+'"]')},a=function(){var t=i(),a=!1;if(t.length){var u=t.offset().top,c=window.pageYOffset;u>c&&u+t.height()');this.$().append(r);var s=this.$(),i=this.$(".Post-mentionedBy"),a=function(){!r.hasClass("in")&&r.is(":visible")||(m.render(r[0],o.map((function(e){return m("li",{"data-number":e.number()},d.a.component({post:e,onclick:t.bind(n)}))}))),r.show().css("top",i.offset().top-s.offset().top+i.outerHeight(!0)).css("left",i.offsetParent().offset().left-s.offset().left).css("max-width",s.width()),setTimeout((function(){return r.off("transitionend").addClass("in")})))};i.add(r).hover((function(){clearTimeout(e),e=setTimeout(a,250)}),(function(){clearTimeout(e),e=setTimeout(t,250)})),this.$().find(".Post-mentionedBy-summary a").hover((function(){r.find('[data-number="'+$(this).data("number")+'"]').addClass("active")}),(function(){r.find("[data-number]").removeClass("active")}))}})),Object(c.extend)(f.a.prototype,"footerItems",(function(e){var n=this,o=this.attrs.post.mentionedBy();if(o&&o.length){var r=[],s=o.sort((function(t){return t.user()===app.session.user?-1:0})).filter((function(t){var e=t.user();if(-1===r.indexOf(e))return r.push(e),!0})),i=s.length>4,a=s.slice(0,i?3:4).map((function(e){var o=e.user();return m(P.a,{href:app.route.post(e),onclick:t.bind(n),"data-number":e.number()},app.session.user===o?app.translator.trans("flarum-mentions.forum.post.you_text"):T()(o))}));if(i){var u=s.length-a.length;a.push(app.translator.trans("flarum-mentions.forum.post.others_text",{count:u}))}e.add("replies",m("div",{className:"Post-mentionedBy"},m("span",{className:"Post-mentionedBy-summary"},O()("fas fa-reply"),app.translator.trans("flarum-mentions.forum.post.mentioned_by"+(s[0].user()===app.session.user?"_self":"")+"_text",{count:a.length,users:_()(a)}))))}}))}(),Object(o.extend)(H.a.prototype,"actionItems",(function(t){var e=this.attrs.post;e.isHidden()||app.session.user&&!e.discussion().canReply()||t.add("reply",m(A.a,{className:"Button Button--link",onclick:function(){return R(e)}},app.translator.trans("flarum-mentions.forum.post.reply_link")))})),K(),lt(),s.a.notificationComponents.postMentioned=vt,s.a.notificationComponents.userMentioned=bt,Object(o.extend)(a.a.prototype,"notificationTypes",(function(t){t.add("postMentioned",{name:"postMentioned",icon:"fas fa-reply",label:s.a.translator.trans("flarum-mentions.forum.settings.notify_post_mentioned_label")}),t.add("userMentioned",{name:"userMentioned",icon:"fas fa-at",label:s.a.translator.trans("flarum-mentions.forum.settings.notify_user_mentioned_label")})})),s.a.routes["user.mentions"]={path:"/u/:username/mentions",component:$t},Object(o.extend)(gt.a.prototype,"navItems",(function(t){var e=this.user;t.add("mentions",wt.a.component({href:s.a.route("user.mentions",{username:e.slug()}),name:"mentions",icon:"fas fa-at"},s.a.translator.trans("flarum-mentions.forum.user.mentions_link")),80)})),u.getPlainContent.removeSelectors.push("a.PostMention")}))}]);
//# sourceMappingURL=forum.js.map
\ No newline at end of file
diff --git a/extensions/mentions/js/dist/forum.js.map b/extensions/mentions/js/dist/forum.js.map
index a7782f344..8f95a8967 100644
--- a/extensions/mentions/js/dist/forum.js.map
+++ b/extensions/mentions/js/dist/forum.js.map
@@ -1 +1 @@
-{"version":3,"sources":["webpack://@flarum/mentions/webpack/bootstrap","webpack://@flarum/mentions/external \"flarum.core.compat['common/extend']\"","webpack://@flarum/mentions/external \"flarum.core.compat['app']\"","webpack://@flarum/mentions/external \"flarum.core.compat['extend']\"","webpack://@flarum/mentions/external \"flarum.core.compat['utils/string']\"","webpack://@flarum/mentions/external \"flarum.core.compat['forum/components/CommentPost']\"","webpack://@flarum/mentions/external \"flarum.core.compat['forum/components/PostPreview']\"","webpack://@flarum/mentions/external \"flarum.core.compat['common/helpers/username']\"","webpack://@flarum/mentions/external \"flarum.core.compat['components/CommentPost']\"","webpack://@flarum/mentions/external \"flarum.core.compat['forum/components/EditPostComposer']\"","webpack://@flarum/mentions/external \"flarum.core.compat['Fragment']\"","webpack://@flarum/mentions/external \"flarum.core.compat['components/Notification']\"","webpack://@flarum/mentions/external \"flarum.core.compat['common/components/TextEditor']\"","webpack://@flarum/mentions/external \"flarum.core.compat['helpers/username']\"","webpack://@flarum/mentions/external \"flarum.core.compat['utils/extractText']\"","webpack://@flarum/mentions/external \"flarum.core.compat['components/NotificationGrid']\"","webpack://@flarum/mentions/external \"flarum.core.compat['common/components/LoadingIndicator']\"","webpack://@flarum/mentions/external \"flarum.core.compat['common/Model']\"","webpack://@flarum/mentions/external \"flarum.core.compat['common/models/Post']\"","webpack://@flarum/mentions/external \"flarum.core.compat['common/components/Link']\"","webpack://@flarum/mentions/external \"flarum.core.compat['common/helpers/punctuateSeries']\"","webpack://@flarum/mentions/external \"flarum.core.compat['common/helpers/icon']\"","webpack://@flarum/mentions/external \"flarum.core.compat['components/Button']\"","webpack://@flarum/mentions/external \"flarum.core.compat['forum/utils/DiscussionControls']\"","webpack://@flarum/mentions/external \"flarum.core.compat['helpers/icon']\"","webpack://@flarum/mentions/external \"flarum.core.compat['common/components/TextEditorButton']\"","webpack://@flarum/mentions/external \"flarum.core.compat['forum/components/ReplyComposer']\"","webpack://@flarum/mentions/external \"flarum.core.compat['common/helpers/avatar']\"","webpack://@flarum/mentions/external \"flarum.core.compat['common/helpers/highlight']\"","webpack://@flarum/mentions/external \"flarum.core.compat['forum/utils/KeyboardNavigatable']\"","webpack://@flarum/mentions/external \"flarum.core.compat['common/utils/string']\"","webpack://@flarum/mentions/external \"flarum.core.compat['common/utils/throttleDebounce']\"","webpack://@flarum/mentions/external \"flarum.core.compat['components/UserPage']\"","webpack://@flarum/mentions/external \"flarum.core.compat['components/LinkButton']\"","webpack://@flarum/mentions/external \"flarum.core.compat['components/PostsUserPage']\"","webpack://@flarum/mentions/./src/forum/utils/getCleanDisplayName.js","webpack://@flarum/mentions/./src/forum/utils/getMentionText.js","webpack://@flarum/mentions/./src/forum/utils/reply.js","webpack://@flarum/mentions/./node_modules/@babel/runtime/helpers/esm/setPrototypeOf.js","webpack://@flarum/mentions/./node_modules/@babel/runtime/helpers/esm/inheritsLoose.js","webpack://@flarum/mentions/./src/forum/fragments/PostQuoteButton.js","webpack://@flarum/mentions/./src/forum/addPostQuoteButton.js","webpack://@flarum/mentions/./src/forum/utils/selectedText.js","webpack://@flarum/mentions/./src/forum/fragments/AutocompleteDropdown.js","webpack://@flarum/mentions/./src/forum/addComposerAutocomplete.js","webpack://@flarum/mentions/./src/forum/components/PostMentionedNotification.js","webpack://@flarum/mentions/./src/forum/components/UserMentionedNotification.js","webpack://@flarum/mentions/./src/forum/components/MentionsUserPage.js","webpack://@flarum/mentions/./src/forum/utils/textFormatter.js","webpack://@flarum/mentions/./src/forum/index.js","webpack://@flarum/mentions/./src/forum/addPostMentionPreviews.js","webpack://@flarum/mentions/./src/forum/addMentionedByList.js","webpack://@flarum/mentions/./src/forum/addPostReplyAction.js"],"names":["installedModules","__webpack_require__","moduleId","exports","module","i","l","modules","call","m","c","d","name","getter","o","Object","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","prototype","hasOwnProperty","p","s","flarum","core","compat","getDeletedUserText","app","translator","trans","getCleanDisplayName","user","useDisplayName","displayName","username","replace","getMentionText","postId","undefined","forum","attribute","id","insertMention","post","composer","quote","mention","fields","content","body","attrs","originalContent","cursorPosition","editor","getSelectionRange","preceding","slice","precedingNewlines","length","match","insertAtCursor","Array","join","trim","reply","bodyMatches","EditPostComposer","discussion","DiscussionControls","replyAction","then","_setPrototypeOf","setPrototypeOf","__proto__","_inheritsLoose","subClass","superClass","constructor","PostQuoteButton","view","class","onclick","icon","className","show","left","top","$this","this","$","parentOffset","offsetParent","offset","css","hideHandler","hide","document","on","showStart","window","scrollTop","outerHeight","showEnd","right","bottom","outerWidth","off","Fragment","addPostQuoteButton","extend","CommentPost","isHidden","session","canReply","$postBody","$container","button","handler","e","setTimeout","selection","getSelection","rangeCount","range","getRangeAt","parent","commonAncestorContainer","contains","clone","append","cloneContents","find","replaceWith","alt","src","innerText","href","text","selectedText","render","rects","getClientRects","firstRect","clientY","clientX","lastRect","after","addEventListener","AutocompleteDropdown","items","active","index","keyWasJustPressed","map","item","navigate","delta","setIndex","clearTimeout","keyWasJustPressedTimeout","complete","eq","click","scrollToItem","$dropdown","$items","rangedIndex","$item","removeClass","addClass","dropdownScroll","dropdownTop","dropdownBottom","itemTop","itemBottom","parseInt","stop","animate","throttledSearch","throttle","typed","searched","returnedUsers","returnedUserIds","dropdown","buildSuggestions","typedLower","toLowerCase","includes","store","filter","q","page","limit","results","forEach","u","has","add","push","addComposerAutocomplete","TextEditor","$editor","wrap","navigator","KeyboardNavigatable","when","onUp","onDown","onSelect","onCancel","bindTo","params","relMentionStart","absMentionStart","matchTyped","from","all","Set","inputListeners","cursor","lastChunk","getLastNChars","substr","test","substring","makeSuggestion","replacement","usernameHelper","children","highlight","replaceBeforeCursor","applySuggestion","onmouseenter","avatar","userMatches","some","suggestions","ReplyComposer","composerAttrs","composerPost","posts","contentType","number","sort","a","b","createdAt","splice","truncate","contentPlain","coordinates","getCaretCoordinates","width","height","Math","max","PostMentionedNotification","notification","subject","route","replyNumber","fromUser","count","excerpt","Notification","UserMentionedNotification","MentionsUserPage","loadResults","type","mentioned","loadLimit","PostsUserPage","filterUserMentions","tag","hasAttribute","getBy","getAttribute","getById","setAttribute","slug","extractText","invalidate","filterPostMentions","initializers","addPreviews","contentHtml","oldPostContentHtml","isEditing","parentPost","$parentPost","set","preventDefault","each","timeout","data","$preview","getPostElement","showPreview","$post","visible","pageYOffset","positionPreview","previewHeight","showPost","title","PostPreview","component","LoadingIndicator","hidePreview","hasClass","one","cancelable","hover","stopPropagation","addPostMentionPreviews","Post","mentionedBy","Model","hasMany","replies","is","data-number","users","repliers","indexOf","overLimit","names","punctuateSeries","addMentionedByList","notificationComponents","postMentioned","userMentioned","NotificationGrid","label","routes","path","UserPage","LinkButton","getPlainContent","removeSelectors"],"mappings":"2BACE,IAAIA,EAAmB,GAGvB,SAASC,EAAoBC,GAG5B,GAAGF,EAAiBE,GACnB,OAAOF,EAAiBE,GAAUC,QAGnC,IAAIC,EAASJ,EAAiBE,GAAY,CACzCG,EAAGH,EACHI,GAAG,EACHH,QAAS,IAUV,OANAI,EAAQL,GAAUM,KAAKJ,EAAOD,QAASC,EAAQA,EAAOD,QAASF,GAG/DG,EAAOE,GAAI,EAGJF,EAAOD,QA0Df,OArDAF,EAAoBQ,EAAIF,EAGxBN,EAAoBS,EAAIV,EAGxBC,EAAoBU,EAAI,SAASR,EAASS,EAAMC,GAC3CZ,EAAoBa,EAAEX,EAASS,IAClCG,OAAOC,eAAeb,EAASS,EAAM,CAAEK,YAAY,EAAMC,IAAKL,KAKhEZ,EAAoBkB,EAAI,SAAShB,GACX,oBAAXiB,QAA0BA,OAAOC,aAC1CN,OAAOC,eAAeb,EAASiB,OAAOC,YAAa,CAAEC,MAAO,WAE7DP,OAAOC,eAAeb,EAAS,aAAc,CAAEmB,OAAO,KAQvDrB,EAAoBsB,EAAI,SAASD,EAAOE,GAEvC,GADU,EAAPA,IAAUF,EAAQrB,EAAoBqB,IAC/B,EAAPE,EAAU,OAAOF,EACpB,GAAW,EAAPE,GAA8B,iBAAVF,GAAsBA,GAASA,EAAMG,WAAY,OAAOH,EAChF,IAAII,EAAKX,OAAOY,OAAO,MAGvB,GAFA1B,EAAoBkB,EAAEO,GACtBX,OAAOC,eAAeU,EAAI,UAAW,CAAET,YAAY,EAAMK,MAAOA,IACtD,EAAPE,GAA4B,iBAATF,EAAmB,IAAI,IAAIM,KAAON,EAAOrB,EAAoBU,EAAEe,EAAIE,EAAK,SAASA,GAAO,OAAON,EAAMM,IAAQC,KAAK,KAAMD,IAC9I,OAAOF,GAIRzB,EAAoB6B,EAAI,SAAS1B,GAChC,IAAIS,EAAST,GAAUA,EAAOqB,WAC7B,WAAwB,OAAOrB,EAAgB,SAC/C,WAA8B,OAAOA,GAEtC,OADAH,EAAoBU,EAAEE,EAAQ,IAAKA,GAC5BA,GAIRZ,EAAoBa,EAAI,SAASiB,EAAQC,GAAY,OAAOjB,OAAOkB,UAAUC,eAAe1B,KAAKuB,EAAQC,IAGzG/B,EAAoBkC,EAAI,GAIjBlC,EAAoBA,EAAoBmC,EAAI,I,gBClFrDhC,EAAOD,QAAUkC,OAAOC,KAAKC,OAAO,kB,cCApCnC,EAAOD,QAAUkC,OAAOC,KAAKC,OAAY,K,cCAzCnC,EAAOD,QAAUkC,OAAOC,KAAKC,OAAe,Q,cCA5CnC,EAAOD,QAAUkC,OAAOC,KAAKC,OAAO,iB,cCApCnC,EAAOD,QAAUkC,OAAOC,KAAKC,OAAO,iC,cCApCnC,EAAOD,QAAUkC,OAAOC,KAAKC,OAAO,iC,cCApCnC,EAAOD,QAAUkC,OAAOC,KAAKC,OAAO,4B,cCApCnC,EAAOD,QAAUkC,OAAOC,KAAKC,OAAO,2B,cCApCnC,EAAOD,QAAUkC,OAAOC,KAAKC,OAAO,sC,cCApCnC,EAAOD,QAAUkC,OAAOC,KAAKC,OAAiB,U,cCA9CnC,EAAOD,QAAUkC,OAAOC,KAAKC,OAAO,4B,cCApCnC,EAAOD,QAAUkC,OAAOC,KAAKC,OAAO,iC,cCApCnC,EAAOD,QAAUkC,OAAOC,KAAKC,OAAO,qB,cCApCnC,EAAOD,QAAUkC,OAAOC,KAAKC,OAAO,sB,eCApCnC,EAAOD,QAAUkC,OAAOC,KAAKC,OAAO,gC,cCApCnC,EAAOD,QAAUkC,OAAOC,KAAKC,OAAO,uC,cCApCnC,EAAOD,QAAUkC,OAAOC,KAAKC,OAAO,iB,cCApCnC,EAAOD,QAAUkC,OAAOC,KAAKC,OAAO,uB,cCApCnC,EAAOD,QAAUkC,OAAOC,KAAKC,OAAO,2B,cCApCnC,EAAOD,QAAUkC,OAAOC,KAAKC,OAAO,mC,cCApCnC,EAAOD,QAAUkC,OAAOC,KAAKC,OAAO,wB,cCApCnC,EAAOD,QAAUkC,OAAOC,KAAKC,OAAO,sB,cCApCnC,EAAOD,QAAUkC,OAAOC,KAAKC,OAAO,mC,cCApCnC,EAAOD,QAAUkC,OAAOC,KAAKC,OAAO,iB,cCApCnC,EAAOD,QAAUkC,OAAOC,KAAKC,OAAO,uC,cCApCnC,EAAOD,QAAUkC,OAAOC,KAAKC,OAAO,mC,cCApCnC,EAAOD,QAAUkC,OAAOC,KAAKC,OAAO,0B,cCApCnC,EAAOD,QAAUkC,OAAOC,KAAKC,OAAO,6B,cCApCnC,EAAOD,QAAUkC,OAAOC,KAAKC,OAAO,oC,cCApCnC,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","file":"forum.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 36);\n","module.exports = flarum.core.compat['common/extend'];","module.exports = flarum.core.compat['app'];","module.exports = flarum.core.compat['extend'];","module.exports = flarum.core.compat['utils/string'];","module.exports = flarum.core.compat['forum/components/CommentPost'];","module.exports = flarum.core.compat['forum/components/PostPreview'];","module.exports = flarum.core.compat['common/helpers/username'];","module.exports = flarum.core.compat['components/CommentPost'];","module.exports = flarum.core.compat['forum/components/EditPostComposer'];","module.exports = flarum.core.compat['Fragment'];","module.exports = flarum.core.compat['components/Notification'];","module.exports = flarum.core.compat['common/components/TextEditor'];","module.exports = flarum.core.compat['helpers/username'];","module.exports = flarum.core.compat['utils/extractText'];","module.exports = flarum.core.compat['components/NotificationGrid'];","module.exports = flarum.core.compat['common/components/LoadingIndicator'];","module.exports = flarum.core.compat['common/Model'];","module.exports = flarum.core.compat['common/models/Post'];","module.exports = flarum.core.compat['common/components/Link'];","module.exports = flarum.core.compat['common/helpers/punctuateSeries'];","module.exports = flarum.core.compat['common/helpers/icon'];","module.exports = flarum.core.compat['components/Button'];","module.exports = flarum.core.compat['forum/utils/DiscussionControls'];","module.exports = flarum.core.compat['helpers/icon'];","module.exports = flarum.core.compat['common/components/TextEditorButton'];","module.exports = flarum.core.compat['forum/components/ReplyComposer'];","module.exports = flarum.core.compat['common/helpers/avatar'];","module.exports = flarum.core.compat['common/helpers/highlight'];","module.exports = flarum.core.compat['forum/utils/KeyboardNavigatable'];","module.exports = flarum.core.compat['common/utils/string'];","module.exports = flarum.core.compat['common/utils/throttleDebounce'];","module.exports = flarum.core.compat['components/UserPage'];","module.exports = flarum.core.compat['components/LinkButton'];","module.exports = flarum.core.compat['components/PostsUserPage'];","/**\n * Whether to use the old mentions format.\n *\n * `'@username'` or `'@\"Display name\"'`\n */\nexport const shouldUseOldFormat = () => app.forum.attribute('allowUsernameMentionFormat') || false;\n\nconst getDeletedUserText = () => app.translator.trans('core.lib.username.deleted_text');\n\n/**\n * Fetches a user's username or display name.\n *\n * Chooses based on the format option set in the admin settings page.\n *\n * @param user An instance of the User model to fetch the username for\n * @param useDisplayName If `true`, uses `user.displayName()`, otherwise, uses `user.username()`\n */\nexport default function getCleanDisplayName(user, useDisplayName = true) {\n if (!user) return getDeletedUserText().replace(/\"#[a-z]{0,3}[0-9]+/, '_');\n\n const text = (useDisplayName ? user.displayName() : user.username()) || getDeletedUserText();\n\n return text.replace(/\"#[a-z]{0,3}[0-9]+/, '_');\n}\n","import getCleanDisplayName, { shouldUseOldFormat } from './getCleanDisplayName';\n\n/**\n * Fetches the mention text for a specified user (and optionally a post ID for replies).\n *\n * Automatically determines which mention syntax to be used based on the option in the\n * admin dashboard. Also performs display name clean-up automatically.\n *\n * @example
New display name syntax
\n * // '@\"User\"#1'\n * getMentionText(User) // User is ID 1, display name is 'User'\n *\n * @example
Replying
\n * // '@\"User\"#p13'\n * getMentionText(User, 13) // User display name is 'User', post ID is 13\n *\n * @example
Using old syntax
\n * // '@username'\n * getMentionText(User) // User's username is 'username'\n */\nexport default function getMentionText(user, postId) {\n if (postId === undefined) {\n if (shouldUseOldFormat()) {\n // Plain @username\n const cleanText = getCleanDisplayName(user, false);\n return `@${cleanText}`;\n }\n // @\"Display name\"#UserID\n const cleanText = getCleanDisplayName(user);\n return `@\"${cleanText}\"${user.id()}`;\n } else {\n // @\"Display name\"#pPostID\n const cleanText = getCleanDisplayName(user);\n return `@\"${cleanText}\"#p${postId}`;\n }\n}\n","import DiscussionControls from 'flarum/forum/utils/DiscussionControls';\nimport EditPostComposer from 'flarum/forum/components/EditPostComposer';\nimport getMentionText from './getMentionText';\n\nfunction insertMention(post, composer, quote) {\n const user = post.user();\n const mention = getMentionText(user, post.id());\n\n // If the composer is empty, then assume we're starting a new reply.\n // In which case we don't want the user to have to confirm if they\n // close the composer straight away.\n if (!composer.fields.content()) {\n composer.body.attrs.originalContent = mention;\n }\n\n const cursorPosition = composer.editor.getSelectionRange()[0];\n const preceding = composer.fields.content().slice(0, cursorPosition);\n const precedingNewlines = preceding.length == 0 ? 0 : 3 - preceding.match(/(\\n{0,2})$/)[0].length;\n\n composer.editor.insertAtCursor(\n Array(precedingNewlines).join('\\n') + // Insert up to two newlines, depending on preceding whitespace\n (quote ? '> ' + mention + quote.trim().replace(/\\n/g, '\\n> ') + '\\n\\n' : mention),\n false\n );\n}\n\nexport default function reply(post, quote) {\n if (app.composer.bodyMatches(EditPostComposer) && app.composer.body.attrs.post.discussion() === post.discussion()) {\n // If we're already editing a post in the discussion of post we're quoting,\n // insert the mention directly.\n insertMention(post, app.composer, quote);\n } else {\n // The default \"Reply\" action behavior will only open a new composer if\n // necessary, but it will always be a ReplyComposer, hence the exceptional\n // case above.\n DiscussionControls.replyAction.call(post.discussion()).then((composer) => insertMention(post, composer, quote));\n }\n}\n","export default function _setPrototypeOf(o, p) {\n _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {\n o.__proto__ = p;\n return o;\n };\n\n return _setPrototypeOf(o, p);\n}","import setPrototypeOf from \"./setPrototypeOf.js\";\nexport default function _inheritsLoose(subClass, superClass) {\n subClass.prototype = Object.create(superClass.prototype);\n subClass.prototype.constructor = subClass;\n setPrototypeOf(subClass, superClass);\n}","import Fragment from 'flarum/Fragment';\nimport icon from 'flarum/helpers/icon';\n\nimport reply from '../utils/reply';\n\nexport default class PostQuoteButton extends Fragment {\n constructor(post) {\n super();\n\n this.post = post;\n }\n\n view() {\n return (\n \n );\n }\n\n show(left, top) {\n const $this = this.$().show();\n const parentOffset = $this.offsetParent().offset();\n\n $this\n .css('left', left - parentOffset.left)\n .css('top', top - parentOffset.top);\n\n\n this.hideHandler = this.hide.bind(this);\n $(document).on('mouseup', this.hideHandler);\n }\n\n showStart(left, top) {\n const $this = this.$();\n\n this.show(left, $(window).scrollTop() + top - $this.outerHeight() - 5);\n }\n\n showEnd(right, bottom) {\n const $this = this.$();\n\n this.show(right - $this.outerWidth(), $(window).scrollTop() + bottom + 5);\n }\n\n hide() {\n this.$().hide();\n $(document).off('mouseup', this.hideHandler);\n }\n}\n","import { extend } from 'flarum/extend';\nimport CommentPost from 'flarum/components/CommentPost';\n\nimport PostQuoteButton from './fragments/PostQuoteButton';\nimport selectedText from './utils/selectedText';\n\nexport default function addPostQuoteButton() {\n extend(CommentPost.prototype, 'oncreate', function() {\n const post = this.attrs.post;\n\n if (post.isHidden() || (app.session.user && !post.discussion().canReply())) return;\n\n const $postBody = this.$('.Post-body');\n\n // Wrap the quote button in a wrapper element so that we can render\n // button into it.\n const $container = $('');\n\n const button = new PostQuoteButton(post);\n\n const handler = function(e) {\n setTimeout(() => {\n const content = selectedText($postBody);\n if (content) {\n button.content = content;\n m.render($container[0], button.render());\n\n const rects = window.getSelection().getRangeAt(0).getClientRects();\n const firstRect = rects[0];\n\n if (e.clientY < firstRect.bottom && e.clientX - firstRect.right < firstRect.left - e.clientX) {\n button.showStart(firstRect.left, firstRect.top);\n } else {\n const lastRect = rects[rects.length - 1];\n button.showEnd(lastRect.right, lastRect.bottom);\n }\n }\n }, 1);\n };\n\n this.$().after($container).on('mouseup', handler);\n\n if ('ontouchstart' in window) {\n document.addEventListener('selectionchange', handler, false);\n }\n });\n}\n","/**\n * Finds the selected text in the provided composer body.\n */\nexport default function selectedText(body) {\n const selection = window.getSelection();\n\n if (selection?.rangeCount) {\n const range = selection.getRangeAt(0);\n const parent = range.commonAncestorContainer;\n\n if (body[0] === parent || $.contains(body[0], parent)) {\n const clone = $('
').append(range.cloneContents());\n\n // Replace emoji images with their shortcode (found in alt attribute)\n clone.find('img.emoji').replaceWith(function () {\n return this.alt;\n });\n\n // Replace all other images with a Markdown image\n clone.find('img').replaceWith(function () {\n return `![](${this.src})`;\n });\n\n // Replace all links with a Markdown link\n clone.find('a').replaceWith(function () {\n return `[${this.innerText}](${this.href})`;\n });\n\n return clone.text();\n }\n }\n return '';\n}\n","import Fragment from 'flarum/Fragment';\n\nexport default class AutocompleteDropdown extends Fragment {\n items = [];\n active = false;\n index = 0;\n keyWasJustPressed = false;\n\n view() {\n return (\n
\n {this.items.map(item =>
{item}
)}\n
\n );\n }\n\n show(left, top) {\n this.$().show().css({\n left: left + 'px',\n top: top + 'px'\n });\n this.active = true;\n }\n\n hide() {\n this.$().hide();\n this.active = false;\n }\n\n navigate(delta) {\n this.keyWasJustPressed = true;\n this.setIndex(this.index + delta, true);\n clearTimeout(this.keyWasJustPressedTimeout);\n this.keyWasJustPressedTimeout = setTimeout(() => this.keyWasJustPressed = false, 500);\n }\n\n complete() {\n this.$('li').eq(this.index).find('button').click();\n }\n\n setIndex(index, scrollToItem) {\n if (this.keyWasJustPressed && !scrollToItem) return;\n\n const $dropdown = this.$();\n const $items = $dropdown.find('li');\n let rangedIndex = index;\n\n if (rangedIndex < 0) {\n rangedIndex = $items.length - 1;\n } else if (rangedIndex >= $items.length) {\n rangedIndex = 0;\n }\n\n this.index = rangedIndex;\n\n const $item = $items.removeClass('active').eq(rangedIndex).addClass('active');\n\n if (scrollToItem) {\n const dropdownScroll = $dropdown.scrollTop();\n const dropdownTop = $dropdown.offset().top;\n const dropdownBottom = dropdownTop + $dropdown.outerHeight();\n const itemTop = $item.offset().top;\n const itemBottom = itemTop + $item.outerHeight();\n\n let scrollTop;\n if (itemTop < dropdownTop) {\n scrollTop = dropdownScroll - dropdownTop + itemTop - parseInt($dropdown.css('padding-top'), 10);\n } else if (itemBottom > dropdownBottom) {\n scrollTop = dropdownScroll - dropdownBottom + itemBottom + parseInt($dropdown.css('padding-bottom'), 10);\n }\n\n if (typeof scrollTop !== 'undefined') {\n $dropdown.stop(true).animate({ scrollTop }, 100);\n }\n }\n }\n}\n","import { extend } from 'flarum/common/extend';\nimport TextEditor from 'flarum/common/components/TextEditor';\nimport TextEditorButton from 'flarum/common/components/TextEditorButton';\nimport ReplyComposer from 'flarum/forum/components/ReplyComposer';\nimport EditPostComposer from 'flarum/forum/components/EditPostComposer';\nimport avatar from 'flarum/common/helpers/avatar';\nimport usernameHelper from 'flarum/common/helpers/username';\nimport highlight from 'flarum/common/helpers/highlight';\nimport KeyboardNavigatable from 'flarum/forum/utils/KeyboardNavigatable';\nimport { truncate } from 'flarum/common/utils/string';\nimport { throttle } from 'flarum/common/utils/throttleDebounce';\n\nimport AutocompleteDropdown from './fragments/AutocompleteDropdown';\nimport getMentionText from './utils/getMentionText';\n\nconst throttledSearch = throttle(\n 250, // 250ms timeout\n function (typed, searched, returnedUsers, returnedUserIds, dropdown, buildSuggestions) {\n const typedLower = typed.toLowerCase();\n if (!searched.includes(typedLower)) {\n app.store.find('users', { filter: { q: typed }, page: { limit: 5 } }).then((results) => {\n results.forEach((u) => {\n if (!returnedUserIds.has(u.id())) {\n returnedUserIds.add(u.id());\n returnedUsers.push(u);\n }\n });\n \n buildSuggestions();\n });\n searched.push(typedLower);\n }\n }\n);\n\nexport default function addComposerAutocomplete() {\n const $container = $('');\n const dropdown = new AutocompleteDropdown();\n\n extend(TextEditor.prototype, 'oncreate', function () {\n const $editor = this.$('.TextEditor-editor').wrap('');\n\n this.navigator = new KeyboardNavigatable();\n this.navigator\n .when(() => dropdown.active)\n .onUp(() => dropdown.navigate(-1))\n .onDown(() => dropdown.navigate(1))\n .onSelect(dropdown.complete.bind(dropdown))\n .onCancel(dropdown.hide.bind(dropdown))\n .bindTo($editor);\n\n $editor.after($container);\n });\n\n extend(TextEditor.prototype, 'buildEditorParams', function (params) {\n const searched = [];\n let relMentionStart;\n let absMentionStart;\n let typed;\n let matchTyped;\n\n // We store users returned from an API here to preserve order in which they are returned\n // This prevents the user list jumping around while users are returned.\n // We also use a hashset for user IDs to provide O(1) lookup for the users already in the list.\n const returnedUsers = Array.from(app.store.all('users'));\n const returnedUserIds = new Set(returnedUsers.map((u) => u.id()));\n\n const applySuggestion = (replacement) => {\n app.composer.editor.replaceBeforeCursor(absMentionStart - 1, replacement + ' ');\n\n dropdown.hide();\n };\n\n params.inputListeners.push(function () {\n const selection = app.composer.editor.getSelectionRange();\n\n const cursor = selection[0];\n\n if (selection[1] - cursor > 0) return;\n\n // Search backwards from the cursor for an '@' symbol. If we find one,\n // we will want to show the autocomplete dropdown!\n const lastChunk = app.composer.editor.getLastNChars(30);\n absMentionStart = 0;\n for (let i = lastChunk.length - 1; i >= 0; i--) {\n const character = lastChunk.substr(i, 1);\n if (character === '@' && (i == 0 || /\\s/.test(lastChunk.substr(i - 1, 1)))) {\n relMentionStart = i + 1;\n absMentionStart = cursor - lastChunk.length + i + 1;\n break;\n }\n }\n\n dropdown.hide();\n dropdown.active = false;\n\n if (absMentionStart) {\n typed = lastChunk.substring(relMentionStart).toLowerCase();\n matchTyped = typed.match(/^[\"|“]((?:(?!\"#).)+)$/);\n typed = (matchTyped && matchTyped[1]) || typed;\n\n const makeSuggestion = function (user, replacement, content, className = '') {\n const username = usernameHelper(user);\n\n if (typed) {\n username.children = [highlight(username.text, typed)];\n delete username.text;\n }\n\n return (\n \n );\n };\n\n const userMatches = function (user) {\n const names = [user.username(), user.displayName()];\n\n return names.some((name) => name.toLowerCase().substr(0, typed.length) === typed);\n };\n\n const buildSuggestions = () => {\n const suggestions = [];\n\n // If the user has started to type a username, then suggest users\n // matching that username.\n if (typed) {\n returnedUsers.forEach((user) => {\n if (!userMatches(user)) return;\n\n suggestions.push(makeSuggestion(user, getMentionText(user), '', 'MentionsDropdown-user'));\n });\n }\n\n // If the user is replying to a discussion, or if they are editing a\n // post, then we can suggest other posts in the discussion to mention.\n // We will add the 5 most recent comments in the discussion which\n // match any username characters that have been typed.\n if (app.composer.bodyMatches(ReplyComposer) || app.composer.bodyMatches(EditPostComposer)) {\n const composerAttrs = app.composer.body.attrs;\n const composerPost = composerAttrs.post;\n const discussion = (composerPost && composerPost.discussion()) || composerAttrs.discussion;\n\n if (discussion) {\n discussion\n .posts()\n // Filter to only comment posts, and replies before this message\n .filter((post) => post && post.contentType() === 'comment' && (!composerPost || post.number() < composerPost.number()))\n // Sort by new to old\n .sort((a, b) => b.createdAt() - a.createdAt())\n // Filter to where the user matches what is being typed\n .filter((post) => {\n const user = post.user();\n return user && userMatches(user);\n })\n // Get the first 5\n .splice(0, 5)\n // Make the suggestions\n .forEach((post) => {\n const user = post.user();\n suggestions.push(\n makeSuggestion(\n user,\n getMentionText(user, post.id()),\n [\n app.translator.trans('flarum-mentions.forum.composer.reply_to_post_text', { number: post.number() }),\n ' — ',\n truncate(post.contentPlain(), 200),\n ],\n 'MentionsDropdown-post'\n )\n );\n });\n }\n }\n\n if (suggestions.length) {\n dropdown.items = suggestions;\n m.render($container[0], dropdown.render());\n\n dropdown.show();\n const coordinates = app.composer.editor.getCaretCoordinates(absMentionStart);\n const width = dropdown.$().outerWidth();\n const height = dropdown.$().outerHeight();\n const parent = dropdown.$().offsetParent();\n let left = coordinates.left;\n let top = coordinates.top + 15;\n\n // Keep the dropdown inside the editor.\n if (top + height > parent.height()) {\n top = coordinates.top - height - 15;\n }\n if (left + width > parent.width()) {\n left = parent.width() - width;\n }\n\n // Prevent the dropdown from going off screen on mobile\n top = Math.max(-(parent.offset().top - $(document).scrollTop()), top);\n left = Math.max(-parent.offset().left, left);\n\n dropdown.show(left, top);\n } else {\n dropdown.active = false;\n dropdown.hide();\n }\n };\n\n dropdown.active = true;\n\n buildSuggestions();\n\n dropdown.setIndex(0);\n dropdown.$().scrollTop(0);\n\n // Don't send API calls searching for users until at least 2 characters have been typed.\n // This focuses the mention results on users and posts in the discussion.\n if (typed.length > 1) {\n throttledSearch(typed, searched, returnedUsers, returnedUserIds, dropdown, buildSuggestions);\n }\n }\n });\n });\n\n extend(TextEditor.prototype, 'toolbarItems', function (items) {\n items.add(\n 'mention',\n this.attrs.composer.editor.insertAtCursor(' @')} icon=\"fas fa-at\">\n {app.translator.trans('flarum-mentions.forum.composer.mention_tooltip')}\n \n );\n });\n}\n","import Notification from 'flarum/components/Notification';\nimport { truncate } from 'flarum/utils/string';\n\nexport default class PostMentionedNotification extends Notification {\n icon() {\n return 'fas fa-reply';\n }\n\n href() {\n const notification = this.attrs.notification;\n const post = notification.subject();\n const content = notification.content();\n\n return app.route.discussion(post.discussion(), content && content.replyNumber);\n }\n\n content() {\n const notification = this.attrs.notification;\n const user = notification.fromUser();\n\n return app.translator.trans('flarum-mentions.forum.notifications.post_mentioned_text', {user, count: 1});\n }\n\n excerpt() {\n return truncate(this.attrs.notification.subject().contentPlain(), 200);\n }\n}\n","import Notification from 'flarum/components/Notification';\nimport { truncate } from 'flarum/utils/string';\n\nexport default class UserMentionedNotification extends Notification {\n icon() {\n return 'fas fa-at';\n }\n\n href() {\n const post = this.attrs.notification.subject();\n\n return app.route.discussion(post.discussion(), post.number());\n }\n\n content() {\n const user = this.attrs.notification.fromUser();\n\n return app.translator.trans('flarum-mentions.forum.notifications.user_mentioned_text', {user});\n }\n\n excerpt() {\n return truncate(this.attrs.notification.subject().contentPlain(), 200);\n }\n}\n","import PostsUserPage from 'flarum/components/PostsUserPage';\n\n/**\n * The `MentionsUserPage` component shows post which user Mentioned at\n */\nexport default class MentionsUserPage extends PostsUserPage {\n /**\n * Load a new page of the user's activity feed.\n *\n * @param {Integer} [offset] The position to start getting results from.\n * @return {Promise}\n * @protected\n */\n loadResults(offset) {\n return app.store.find('posts', {\n filter: {\n type: 'comment',\n mentioned: this.user.id()\n },\n page: {offset, limit: this.loadLimit},\n sort: '-createdAt'\n });\n }\n}\n","import username from 'flarum/helpers/username';\nimport extractText from 'flarum/utils/extractText';\n\nexport function filterUserMentions(tag) {\n let user;\n\n if (app.forum.attribute('allowUsernameMentionFormat') && tag.hasAttribute('username'))\n user = app.store.getBy('users', 'username', tag.getAttribute('username'));\n else if (tag.hasAttribute('id'))\n user = app.store.getById('users', tag.getAttribute('id'));\n\n if (user) {\n tag.setAttribute('id', user.id());\n tag.setAttribute('slug', user.slug());\n tag.setAttribute('displayname', extractText(username(user)));\n\n return true;\n }\n\n tag.invalidate();\n}\n\nexport function filterPostMentions(tag) {\n const post = app.store.getById('posts', tag.getAttribute('id'));\n\n if (post) {\n tag.setAttribute('discussionid', post.discussion().id());\n tag.setAttribute('number', post.number());\n tag.setAttribute('displayname', extractText(username(post.user())));\n\n return true;\n }\n}\n","import { extend } from 'flarum/extend';\nimport app from 'flarum/app';\nimport NotificationGrid from 'flarum/components/NotificationGrid';\nimport { getPlainContent } from 'flarum/utils/string';\n\nimport addPostMentionPreviews from './addPostMentionPreviews';\nimport addMentionedByList from './addMentionedByList';\nimport addPostReplyAction from './addPostReplyAction';\nimport addPostQuoteButton from './addPostQuoteButton';\nimport addComposerAutocomplete from './addComposerAutocomplete';\nimport PostMentionedNotification from './components/PostMentionedNotification';\nimport UserMentionedNotification from './components/UserMentionedNotification';\nimport UserPage from 'flarum/components/UserPage'\nimport LinkButton from 'flarum/components/LinkButton';\nimport MentionsUserPage from './components/MentionsUserPage';\n\napp.initializers.add('flarum-mentions', function() {\n // For every mention of a post inside a post's content, set up a hover handler\n // that shows a preview of the mentioned post.\n addPostMentionPreviews();\n\n // In the footer of each post, show information about who has replied (i.e.\n // who the post has been mentioned by).\n addMentionedByList();\n\n // Add a 'reply' control to the footer of each post. When clicked, it will\n // open up the composer and add a post mention to its contents.\n addPostReplyAction();\n\n // Show a Quote button when Post text is selected\n addPostQuoteButton();\n\n // After typing '@' in the composer, show a dropdown suggesting a bunch of\n // posts or users that the user could mention.\n addComposerAutocomplete();\n\n app.notificationComponents.postMentioned = PostMentionedNotification;\n app.notificationComponents.userMentioned = UserMentionedNotification;\n\n // Add notification preferences.\n extend(NotificationGrid.prototype, 'notificationTypes', function(items) {\n items.add('postMentioned', {\n name: 'postMentioned',\n icon: 'fas fa-reply',\n label: app.translator.trans('flarum-mentions.forum.settings.notify_post_mentioned_label')\n });\n\n items.add('userMentioned', {\n name: 'userMentioned',\n icon: 'fas fa-at',\n label: app.translator.trans('flarum-mentions.forum.settings.notify_user_mentioned_label')\n });\n });\n\n // Add mentions tab in user profile\n app.routes['user.mentions'] = {path: '/u/:username/mentions', component: MentionsUserPage};\n extend(UserPage.prototype, 'navItems', function(items) {\n const user = this.user;\n items.add('mentions',\n LinkButton.component({\n href: app.route('user.mentions', {username: user.slug()}),\n name: 'mentions',\n icon: 'fas fa-at'\n }, app.translator.trans('flarum-mentions.forum.user.mentions_link')),\n 80\n );\n });\n\n // Remove post mentions when rendering post previews.\n getPlainContent.removeSelectors.push('a.PostMention');\n});\n\nexport * from './utils/textFormatter';\n","import { extend } from 'flarum/common/extend';\nimport CommentPost from 'flarum/forum/components/CommentPost';\nimport PostPreview from 'flarum/forum/components/PostPreview';\nimport LoadingIndicator from 'flarum/common/components/LoadingIndicator';\n\nexport default function addPostMentionPreviews() {\n function addPreviews() {\n const contentHtml = this.attrs.post.contentHtml();\n\n if (contentHtml === this.oldPostContentHtml || this.isEditing()) return;\n\n this.oldPostContentHtml = contentHtml;\n\n const parentPost = this.attrs.post;\n const $parentPost = this.$();\n\n this.$().on('click', '.UserMention:not(.UserMention--deleted), .PostMention:not(.PostMention--deleted)', function (e) {\n m.route.set(this.getAttribute('href'));\n e.preventDefault();\n });\n\n this.$('.PostMention:not(.PostMention--deleted)').each(function () {\n const $this = $(this);\n const id = $this.data('id');\n let timeout;\n\n // Wrap the mention link in a wrapper element so that we can insert a\n // preview popup as its sibling and relatively position it.\n const $preview = $('
');\n $parentPost.append($preview);\n\n const getPostElement = () => {\n return $(`.PostStream-item[data-id=\"${id}\"]`);\n };\n\n const showPreview = () => {\n // When the user hovers their mouse over the mention, look for the\n // post that it's referring to in the stream, and determine if it's\n // in the viewport. If it is, we will \"pulsate\" it.\n const $post = getPostElement();\n let visible = false;\n if ($post.length) {\n const top = $post.offset().top;\n const scrollTop = window.pageYOffset;\n if (top > scrollTop && top + $post.height() < scrollTop + $(window).height()) {\n $post.addClass('pulsate');\n visible = true;\n }\n }\n\n // Otherwise, we will show a popup preview of the post. If the post\n // hasn't yet been loaded, we will need to do that.\n if (!visible) {\n // Position the preview so that it appears above the mention.\n // (The offsetParent should be .Post-body.)\n const positionPreview = () => {\n const previewHeight = $preview.outerHeight(true);\n let offset = 0;\n\n // If the preview goes off the top of the viewport, reposition it to\n // be below the mention.\n if ($this.offset().top - previewHeight < $(window).scrollTop() + $('#header').outerHeight()) {\n offset += $this.outerHeight(true);\n } else {\n offset -= previewHeight;\n }\n\n $preview\n .show()\n .css('top', $this.offset().top - $parentPost.offset().top + offset)\n .css('left', $this.offsetParent().offset().left - $parentPost.offset().left)\n .css('max-width', $this.offsetParent().width());\n };\n\n const showPost = (post) => {\n const discussion = post.discussion();\n\n m.render($preview[0], [\n discussion !== parentPost.discussion() ? (\n
\n {discussion.title()}\n
\n ) : (\n ''\n ),\n
{PostPreview.component({ post })}
,\n ]);\n positionPreview();\n };\n\n const post = app.store.getById('posts', id);\n if (post && post.discussion()) {\n showPost(post);\n } else {\n m.render($preview[0], LoadingIndicator.component());\n app.store.find('posts', id).then(showPost);\n positionPreview();\n }\n\n setTimeout(() => $preview.off('transitionend').addClass('in'));\n }\n };\n\n const hidePreview = () => {\n getPostElement().removeClass('pulsate');\n if ($preview.hasClass('in')) {\n $preview.removeClass('in').one('transitionend', () => $preview.hide());\n }\n };\n\n // On a touch (mobile) device we cannot hover the link to reveal the preview.\n // Instead we cancel the navigation so that a click reveals the preview.\n // Users can then click on the preview to go to the post if desired.\n $this.on('touchend', (e) => {\n if (e.cancelable) {\n e.preventDefault();\n }\n });\n\n $this\n .add($preview)\n .hover(\n () => {\n clearTimeout(timeout);\n timeout = setTimeout(showPreview, 250);\n },\n () => {\n clearTimeout(timeout);\n getPostElement().removeClass('pulsate');\n timeout = setTimeout(hidePreview, 250);\n }\n )\n .on('touchend', (e) => {\n showPreview();\n e.stopPropagation();\n });\n\n $(document).on('touchend', hidePreview);\n });\n }\n\n extend(CommentPost.prototype, 'oncreate', addPreviews);\n extend(CommentPost.prototype, 'onupdate', addPreviews);\n}\n","import { extend } from 'flarum/common/extend';\nimport Model from 'flarum/common/Model';\nimport Post from 'flarum/common/models/Post';\nimport CommentPost from 'flarum/forum/components/CommentPost';\nimport Link from 'flarum/common/components/Link';\nimport PostPreview from 'flarum/forum/components/PostPreview';\nimport punctuateSeries from 'flarum/common/helpers/punctuateSeries';\nimport username from 'flarum/common/helpers/username';\nimport icon from 'flarum/common/helpers/icon';\n\nexport default function addMentionedByList() {\n Post.prototype.mentionedBy = Model.hasMany('mentionedBy');\n\n function hidePreview() {\n this.$('.Post-mentionedBy-preview')\n .removeClass('in')\n .one('transitionend', function () {\n $(this).hide();\n });\n }\n\n extend(CommentPost.prototype, 'oncreate', function () {\n let timeout;\n const post = this.attrs.post;\n const replies = post.mentionedBy();\n\n if (replies && replies.length) {\n const $preview = $('
');\n this.$().append($preview);\n\n const $parentPost = this.$();\n const $this = this.$('.Post-mentionedBy');\n\n const showPreview = () => {\n if (!$preview.hasClass('in') && $preview.is(':visible')) return;\n\n // When the user hovers their mouse over the list of people who have\n // replied to the post, render a list of reply previews into a\n // popup.\n m.render(\n $preview[0],\n replies.map((reply) => (\n
\n ))\n );\n\n $preview\n .show()\n .css('top', $this.offset().top - $parentPost.offset().top + $this.outerHeight(true))\n .css('left', $this.offsetParent().offset().left - $parentPost.offset().left)\n .css('max-width', $parentPost.width());\n\n setTimeout(() => $preview.off('transitionend').addClass('in'));\n };\n\n $this.add($preview).hover(\n () => {\n clearTimeout(timeout);\n timeout = setTimeout(showPreview, 250);\n },\n () => {\n clearTimeout(timeout);\n timeout = setTimeout(hidePreview, 250);\n }\n );\n\n // Whenever the user hovers their mouse over a particular name in the\n // list of repliers, highlight the corresponding post in the preview\n // popup.\n this.$()\n .find('.Post-mentionedBy-summary a')\n .hover(\n function () {\n $preview.find('[data-number=\"' + $(this).data('number') + '\"]').addClass('active');\n },\n function () {\n $preview.find('[data-number]').removeClass('active');\n }\n );\n }\n });\n\n extend(CommentPost.prototype, 'footerItems', function (items) {\n const post = this.attrs.post;\n const replies = post.mentionedBy();\n\n if (replies && replies.length) {\n const users = [];\n const repliers = replies\n .sort((reply) => (reply.user() === app.session.user ? -1 : 0))\n .filter((reply) => {\n const user = reply.user();\n if (users.indexOf(user) === -1) {\n users.push(user);\n return true;\n }\n });\n\n const limit = 4;\n const overLimit = repliers.length > limit;\n\n // Create a list of unique users who have replied. So even if a user has\n // replied twice, they will only be in this array once.\n const names = repliers.slice(0, overLimit ? limit - 1 : limit).map((reply) => {\n const user = reply.user();\n\n return (\n \n {app.session.user === user ? app.translator.trans('flarum-mentions.forum.post.you_text') : username(user)}\n \n );\n });\n\n // If there are more users that we've run out of room to display, add a \"x\n // others\" name to the end of the list. Clicking on it will display a modal\n // with a full list of names.\n if (overLimit) {\n const count = repliers.length - names.length;\n\n names.push(app.translator.trans('flarum-mentions.forum.post.others_text', { count }));\n }\n\n items.add(\n 'replies',\n
\n );\n }\n });\n}\n","import { extend } from 'flarum/extend';\nimport Button from 'flarum/components/Button';\nimport CommentPost from 'flarum/components/CommentPost';\n\nimport reply from './utils/reply';\n\nexport default function () {\n extend(CommentPost.prototype, 'actionItems', function (items) {\n\n const post = this.attrs.post;\n\n if (post.isHidden() || (app.session.user && !post.discussion().canReply())) return;\n\n items.add('reply',\n \n );\n });\n}\n"],"sourceRoot":""}
\ No newline at end of file
+{"version":3,"sources":["webpack://@flarum/mentions/webpack/bootstrap","webpack://@flarum/mentions/external \"flarum.core.compat['common/extend']\"","webpack://@flarum/mentions/external \"flarum.core.compat['app']\"","webpack://@flarum/mentions/external \"flarum.core.compat['extend']\"","webpack://@flarum/mentions/external \"flarum.core.compat['utils/string']\"","webpack://@flarum/mentions/external \"flarum.core.compat['forum/components/CommentPost']\"","webpack://@flarum/mentions/external \"flarum.core.compat['forum/components/PostPreview']\"","webpack://@flarum/mentions/external \"flarum.core.compat['common/helpers/username']\"","webpack://@flarum/mentions/external \"flarum.core.compat['components/CommentPost']\"","webpack://@flarum/mentions/external \"flarum.core.compat['forum/components/EditPostComposer']\"","webpack://@flarum/mentions/external \"flarum.core.compat['Fragment']\"","webpack://@flarum/mentions/external \"flarum.core.compat['components/Notification']\"","webpack://@flarum/mentions/external \"flarum.core.compat['common/components/TextEditor']\"","webpack://@flarum/mentions/external \"flarum.core.compat['helpers/username']\"","webpack://@flarum/mentions/external \"flarum.core.compat['utils/extractText']\"","webpack://@flarum/mentions/external \"flarum.core.compat['components/NotificationGrid']\"","webpack://@flarum/mentions/external \"flarum.core.compat['common/components/LoadingIndicator']\"","webpack://@flarum/mentions/external \"flarum.core.compat['common/Model']\"","webpack://@flarum/mentions/external \"flarum.core.compat['common/models/Post']\"","webpack://@flarum/mentions/external \"flarum.core.compat['common/components/Link']\"","webpack://@flarum/mentions/external \"flarum.core.compat['common/helpers/punctuateSeries']\"","webpack://@flarum/mentions/external \"flarum.core.compat['common/helpers/icon']\"","webpack://@flarum/mentions/external \"flarum.core.compat['components/Button']\"","webpack://@flarum/mentions/external \"flarum.core.compat['forum/utils/DiscussionControls']\"","webpack://@flarum/mentions/external \"flarum.core.compat['helpers/icon']\"","webpack://@flarum/mentions/external \"flarum.core.compat['common/components/TextEditorButton']\"","webpack://@flarum/mentions/external \"flarum.core.compat['forum/components/ReplyComposer']\"","webpack://@flarum/mentions/external \"flarum.core.compat['common/helpers/avatar']\"","webpack://@flarum/mentions/external \"flarum.core.compat['common/helpers/highlight']\"","webpack://@flarum/mentions/external \"flarum.core.compat['forum/utils/KeyboardNavigatable']\"","webpack://@flarum/mentions/external \"flarum.core.compat['common/utils/string']\"","webpack://@flarum/mentions/external \"flarum.core.compat['common/utils/throttleDebounce']\"","webpack://@flarum/mentions/external \"flarum.core.compat['components/UserPage']\"","webpack://@flarum/mentions/external \"flarum.core.compat['components/LinkButton']\"","webpack://@flarum/mentions/external \"flarum.core.compat['components/PostsUserPage']\"","webpack://@flarum/mentions/./src/forum/utils/getCleanDisplayName.js","webpack://@flarum/mentions/./src/forum/utils/getMentionText.js","webpack://@flarum/mentions/./src/forum/utils/reply.js","webpack://@flarum/mentions/./node_modules/@babel/runtime/helpers/esm/setPrototypeOf.js","webpack://@flarum/mentions/./node_modules/@babel/runtime/helpers/esm/inheritsLoose.js","webpack://@flarum/mentions/./src/forum/fragments/PostQuoteButton.js","webpack://@flarum/mentions/./src/forum/addPostQuoteButton.js","webpack://@flarum/mentions/./src/forum/utils/selectedText.js","webpack://@flarum/mentions/./src/forum/fragments/AutocompleteDropdown.js","webpack://@flarum/mentions/./src/forum/addComposerAutocomplete.js","webpack://@flarum/mentions/./src/forum/components/PostMentionedNotification.js","webpack://@flarum/mentions/./src/forum/components/UserMentionedNotification.js","webpack://@flarum/mentions/./src/forum/components/MentionsUserPage.js","webpack://@flarum/mentions/./src/forum/utils/textFormatter.js","webpack://@flarum/mentions/./src/forum/index.js","webpack://@flarum/mentions/./src/forum/addPostMentionPreviews.js","webpack://@flarum/mentions/./src/forum/addMentionedByList.js","webpack://@flarum/mentions/./src/forum/addPostReplyAction.js"],"names":["installedModules","__webpack_require__","moduleId","exports","module","i","l","modules","call","m","c","d","name","getter","o","Object","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","prototype","hasOwnProperty","p","s","flarum","core","compat","getDeletedUserText","app","translator","trans","getCleanDisplayName","user","useDisplayName","displayName","username","replace","getMentionText","postId","undefined","forum","attribute","id","insertMention","post","composer","quote","mention","fields","content","body","attrs","originalContent","cursorPosition","editor","getSelectionRange","preceding","slice","precedingNewlines","length","match","insertAtCursor","Array","join","trim","reply","bodyMatches","EditPostComposer","discussion","DiscussionControls","replyAction","then","_setPrototypeOf","setPrototypeOf","__proto__","_inheritsLoose","subClass","superClass","constructor","PostQuoteButton","view","class","onclick","icon","className","show","left","top","$this","this","$","parentOffset","offsetParent","offset","css","hideHandler","hide","document","on","showStart","window","scrollTop","outerHeight","showEnd","right","bottom","outerWidth","off","Fragment","addPostQuoteButton","extend","CommentPost","isHidden","session","canReply","$postBody","$container","button","handler","e","setTimeout","selection","getSelection","rangeCount","range","getRangeAt","parent","commonAncestorContainer","contains","clone","append","cloneContents","find","replaceWith","alt","src","innerText","href","text","selectedText","render","rects","getClientRects","firstRect","clientY","clientX","lastRect","after","addEventListener","AutocompleteDropdown","items","active","index","keyWasJustPressed","map","item","navigate","delta","setIndex","clearTimeout","keyWasJustPressedTimeout","complete","eq","click","scrollToItem","$dropdown","$items","rangedIndex","$item","removeClass","addClass","dropdownScroll","dropdownTop","dropdownBottom","itemTop","itemBottom","parseInt","stop","animate","throttledSearch","throttle","typed","searched","returnedUsers","returnedUserIds","dropdown","buildSuggestions","typedLower","toLowerCase","includes","store","filter","q","page","limit","results","forEach","u","has","add","push","addComposerAutocomplete","TextEditor","$editor","wrap","navigator","KeyboardNavigatable","when","onUp","onDown","onSelect","onCancel","bindTo","params","relMentionStart","absMentionStart","matchTyped","from","all","Set","inputListeners","cursor","lastChunk","getLastNChars","substr","test","substring","makeSuggestion","replacement","usernameHelper","children","highlight","replaceBeforeCursor","applySuggestion","onmouseenter","avatar","userMatches","some","suggestions","ReplyComposer","composerAttrs","composerPost","posts","contentType","number","sort","a","b","createdAt","splice","truncate","contentPlain","coordinates","getCaretCoordinates","width","height","Math","max","PostMentionedNotification","notification","subject","route","replyNumber","fromUser","count","excerpt","Notification","UserMentionedNotification","MentionsUserPage","loadResults","type","mentioned","loadLimit","PostsUserPage","filterUserMentions","tag","hasAttribute","getBy","getAttribute","getById","setAttribute","slug","extractText","invalidate","filterPostMentions","initializers","addPreviews","contentHtml","oldPostContentHtml","isEditing","parentPost","$parentPost","set","preventDefault","each","timeout","data","$preview","getPostElement","showPreview","$post","visible","pageYOffset","positionPreview","previewHeight","showPost","title","PostPreview","component","LoadingIndicator","hidePreview","hasClass","one","cancelable","hover","stopPropagation","addPostMentionPreviews","Post","mentionedBy","Model","hasMany","replies","is","data-number","users","repliers","indexOf","overLimit","names","punctuateSeries","addMentionedByList","notificationComponents","postMentioned","userMentioned","NotificationGrid","label","routes","path","UserPage","LinkButton","getPlainContent","removeSelectors"],"mappings":"2BACE,IAAIA,EAAmB,GAGvB,SAASC,EAAoBC,GAG5B,GAAGF,EAAiBE,GACnB,OAAOF,EAAiBE,GAAUC,QAGnC,IAAIC,EAASJ,EAAiBE,GAAY,CACzCG,EAAGH,EACHI,GAAG,EACHH,QAAS,IAUV,OANAI,EAAQL,GAAUM,KAAKJ,EAAOD,QAASC,EAAQA,EAAOD,QAASF,GAG/DG,EAAOE,GAAI,EAGJF,EAAOD,QA0Df,OArDAF,EAAoBQ,EAAIF,EAGxBN,EAAoBS,EAAIV,EAGxBC,EAAoBU,EAAI,SAASR,EAASS,EAAMC,GAC3CZ,EAAoBa,EAAEX,EAASS,IAClCG,OAAOC,eAAeb,EAASS,EAAM,CAAEK,YAAY,EAAMC,IAAKL,KAKhEZ,EAAoBkB,EAAI,SAAShB,GACX,oBAAXiB,QAA0BA,OAAOC,aAC1CN,OAAOC,eAAeb,EAASiB,OAAOC,YAAa,CAAEC,MAAO,WAE7DP,OAAOC,eAAeb,EAAS,aAAc,CAAEmB,OAAO,KAQvDrB,EAAoBsB,EAAI,SAASD,EAAOE,GAEvC,GADU,EAAPA,IAAUF,EAAQrB,EAAoBqB,IAC/B,EAAPE,EAAU,OAAOF,EACpB,GAAW,EAAPE,GAA8B,iBAAVF,GAAsBA,GAASA,EAAMG,WAAY,OAAOH,EAChF,IAAII,EAAKX,OAAOY,OAAO,MAGvB,GAFA1B,EAAoBkB,EAAEO,GACtBX,OAAOC,eAAeU,EAAI,UAAW,CAAET,YAAY,EAAMK,MAAOA,IACtD,EAAPE,GAA4B,iBAATF,EAAmB,IAAI,IAAIM,KAAON,EAAOrB,EAAoBU,EAAEe,EAAIE,EAAK,SAASA,GAAO,OAAON,EAAMM,IAAQC,KAAK,KAAMD,IAC9I,OAAOF,GAIRzB,EAAoB6B,EAAI,SAAS1B,GAChC,IAAIS,EAAST,GAAUA,EAAOqB,WAC7B,WAAwB,OAAOrB,EAAgB,SAC/C,WAA8B,OAAOA,GAEtC,OADAH,EAAoBU,EAAEE,EAAQ,IAAKA,GAC5BA,GAIRZ,EAAoBa,EAAI,SAASiB,EAAQC,GAAY,OAAOjB,OAAOkB,UAAUC,eAAe1B,KAAKuB,EAAQC,IAGzG/B,EAAoBkC,EAAI,GAIjBlC,EAAoBA,EAAoBmC,EAAI,I,gBClFrDhC,EAAOD,QAAUkC,OAAOC,KAAKC,OAAO,kB,cCApCnC,EAAOD,QAAUkC,OAAOC,KAAKC,OAAY,K,cCAzCnC,EAAOD,QAAUkC,OAAOC,KAAKC,OAAe,Q,cCA5CnC,EAAOD,QAAUkC,OAAOC,KAAKC,OAAO,iB,cCApCnC,EAAOD,QAAUkC,OAAOC,KAAKC,OAAO,iC,cCApCnC,EAAOD,QAAUkC,OAAOC,KAAKC,OAAO,iC,cCApCnC,EAAOD,QAAUkC,OAAOC,KAAKC,OAAO,4B,cCApCnC,EAAOD,QAAUkC,OAAOC,KAAKC,OAAO,2B,cCApCnC,EAAOD,QAAUkC,OAAOC,KAAKC,OAAO,sC,cCApCnC,EAAOD,QAAUkC,OAAOC,KAAKC,OAAiB,U,cCA9CnC,EAAOD,QAAUkC,OAAOC,KAAKC,OAAO,4B,cCApCnC,EAAOD,QAAUkC,OAAOC,KAAKC,OAAO,iC,cCApCnC,EAAOD,QAAUkC,OAAOC,KAAKC,OAAO,qB,cCApCnC,EAAOD,QAAUkC,OAAOC,KAAKC,OAAO,sB,eCApCnC,EAAOD,QAAUkC,OAAOC,KAAKC,OAAO,gC,cCApCnC,EAAOD,QAAUkC,OAAOC,KAAKC,OAAO,uC,cCApCnC,EAAOD,QAAUkC,OAAOC,KAAKC,OAAO,iB,cCApCnC,EAAOD,QAAUkC,OAAOC,KAAKC,OAAO,uB,cCApCnC,EAAOD,QAAUkC,OAAOC,KAAKC,OAAO,2B,cCApCnC,EAAOD,QAAUkC,OAAOC,KAAKC,OAAO,mC,cCApCnC,EAAOD,QAAUkC,OAAOC,KAAKC,OAAO,wB,cCApCnC,EAAOD,QAAUkC,OAAOC,KAAKC,OAAO,sB,cCApCnC,EAAOD,QAAUkC,OAAOC,KAAKC,OAAO,mC,cCApCnC,EAAOD,QAAUkC,OAAOC,KAAKC,OAAO,iB,cCApCnC,EAAOD,QAAUkC,OAAOC,KAAKC,OAAO,uC,cCApCnC,EAAOD,QAAUkC,OAAOC,KAAKC,OAAO,mC,cCApCnC,EAAOD,QAAUkC,OAAOC,KAAKC,OAAO,0B,cCApCnC,EAAOD,QAAUkC,OAAOC,KAAKC,OAAO,6B,cCApCnC,EAAOD,QAAUkC,OAAOC,KAAKC,OAAO,oC,cCApCnC,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","file":"forum.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 36);\n","module.exports = flarum.core.compat['common/extend'];","module.exports = flarum.core.compat['app'];","module.exports = flarum.core.compat['extend'];","module.exports = flarum.core.compat['utils/string'];","module.exports = flarum.core.compat['forum/components/CommentPost'];","module.exports = flarum.core.compat['forum/components/PostPreview'];","module.exports = flarum.core.compat['common/helpers/username'];","module.exports = flarum.core.compat['components/CommentPost'];","module.exports = flarum.core.compat['forum/components/EditPostComposer'];","module.exports = flarum.core.compat['Fragment'];","module.exports = flarum.core.compat['components/Notification'];","module.exports = flarum.core.compat['common/components/TextEditor'];","module.exports = flarum.core.compat['helpers/username'];","module.exports = flarum.core.compat['utils/extractText'];","module.exports = flarum.core.compat['components/NotificationGrid'];","module.exports = flarum.core.compat['common/components/LoadingIndicator'];","module.exports = flarum.core.compat['common/Model'];","module.exports = flarum.core.compat['common/models/Post'];","module.exports = flarum.core.compat['common/components/Link'];","module.exports = flarum.core.compat['common/helpers/punctuateSeries'];","module.exports = flarum.core.compat['common/helpers/icon'];","module.exports = flarum.core.compat['components/Button'];","module.exports = flarum.core.compat['forum/utils/DiscussionControls'];","module.exports = flarum.core.compat['helpers/icon'];","module.exports = flarum.core.compat['common/components/TextEditorButton'];","module.exports = flarum.core.compat['forum/components/ReplyComposer'];","module.exports = flarum.core.compat['common/helpers/avatar'];","module.exports = flarum.core.compat['common/helpers/highlight'];","module.exports = flarum.core.compat['forum/utils/KeyboardNavigatable'];","module.exports = flarum.core.compat['common/utils/string'];","module.exports = flarum.core.compat['common/utils/throttleDebounce'];","module.exports = flarum.core.compat['components/UserPage'];","module.exports = flarum.core.compat['components/LinkButton'];","module.exports = flarum.core.compat['components/PostsUserPage'];","/**\n * Whether to use the old mentions format.\n *\n * `'@username'` or `'@\"Display name\"'`\n */\nexport const shouldUseOldFormat = () => app.forum.attribute('allowUsernameMentionFormat') || false;\n\nconst getDeletedUserText = () => app.translator.trans('core.lib.username.deleted_text');\n\n/**\n * Fetches a user's username or display name.\n *\n * Chooses based on the format option set in the admin settings page.\n *\n * @param user An instance of the User model to fetch the username for\n * @param useDisplayName If `true`, uses `user.displayName()`, otherwise, uses `user.username()`\n */\nexport default function getCleanDisplayName(user, useDisplayName = true) {\n if (!user) return getDeletedUserText().replace(/\"#[a-z]{0,3}[0-9]+/, '_');\n\n const text = (useDisplayName ? user.displayName() : user.username()) || getDeletedUserText();\n\n return text.replace(/\"#[a-z]{0,3}[0-9]+/, '_');\n}\n","import getCleanDisplayName, { shouldUseOldFormat } from './getCleanDisplayName';\n\n/**\n * Fetches the mention text for a specified user (and optionally a post ID for replies).\n *\n * Automatically determines which mention syntax to be used based on the option in the\n * admin dashboard. Also performs display name clean-up automatically.\n *\n * @example
New display name syntax
\n * // '@\"User\"#1'\n * getMentionText(User) // User is ID 1, display name is 'User'\n *\n * @example
Replying
\n * // '@\"User\"#p13'\n * getMentionText(User, 13) // User display name is 'User', post ID is 13\n *\n * @example
Using old syntax
\n * // '@username'\n * getMentionText(User) // User's username is 'username'\n */\nexport default function getMentionText(user, postId) {\n if (postId === undefined) {\n if (shouldUseOldFormat()) {\n // Plain @username\n const cleanText = getCleanDisplayName(user, false);\n return `@${cleanText}`;\n }\n // @\"Display name\"#UserID\n const cleanText = getCleanDisplayName(user);\n return `@\"${cleanText}\"${user.id()}`;\n } else {\n // @\"Display name\"#pPostID\n const cleanText = getCleanDisplayName(user);\n return `@\"${cleanText}\"#p${postId}`;\n }\n}\n","import DiscussionControls from 'flarum/forum/utils/DiscussionControls';\nimport EditPostComposer from 'flarum/forum/components/EditPostComposer';\nimport getMentionText from './getMentionText';\n\nfunction insertMention(post, composer, quote) {\n const user = post.user();\n const mention = getMentionText(user, post.id()) + ' ';\n\n // If the composer is empty, then assume we're starting a new reply.\n // In which case we don't want the user to have to confirm if they\n // close the composer straight away.\n if (!composer.fields.content()) {\n composer.body.attrs.originalContent = mention;\n }\n\n const cursorPosition = composer.editor.getSelectionRange()[0];\n const preceding = composer.fields.content().slice(0, cursorPosition);\n const precedingNewlines = preceding.length == 0 ? 0 : 3 - preceding.match(/(\\n{0,2})$/)[0].length;\n\n composer.editor.insertAtCursor(\n Array(precedingNewlines).join('\\n') + // Insert up to two newlines, depending on preceding whitespace\n (quote ? '> ' + mention + quote.trim().replace(/\\n/g, '\\n> ') + '\\n\\n' : mention),\n false\n );\n}\n\nexport default function reply(post, quote) {\n if (app.composer.bodyMatches(EditPostComposer) && app.composer.body.attrs.post.discussion() === post.discussion()) {\n // If we're already editing a post in the discussion of post we're quoting,\n // insert the mention directly.\n insertMention(post, app.composer, quote);\n } else {\n // The default \"Reply\" action behavior will only open a new composer if\n // necessary, but it will always be a ReplyComposer, hence the exceptional\n // case above.\n DiscussionControls.replyAction.call(post.discussion()).then((composer) => insertMention(post, composer, quote));\n }\n}\n","export default function _setPrototypeOf(o, p) {\n _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {\n o.__proto__ = p;\n return o;\n };\n\n return _setPrototypeOf(o, p);\n}","import setPrototypeOf from \"./setPrototypeOf.js\";\nexport default function _inheritsLoose(subClass, superClass) {\n subClass.prototype = Object.create(superClass.prototype);\n subClass.prototype.constructor = subClass;\n setPrototypeOf(subClass, superClass);\n}","import Fragment from 'flarum/Fragment';\nimport icon from 'flarum/helpers/icon';\n\nimport reply from '../utils/reply';\n\nexport default class PostQuoteButton extends Fragment {\n constructor(post) {\n super();\n\n this.post = post;\n }\n\n view() {\n return (\n \n );\n }\n\n show(left, top) {\n const $this = this.$().show();\n const parentOffset = $this.offsetParent().offset();\n\n $this\n .css('left', left - parentOffset.left)\n .css('top', top - parentOffset.top);\n\n\n this.hideHandler = this.hide.bind(this);\n $(document).on('mouseup', this.hideHandler);\n }\n\n showStart(left, top) {\n const $this = this.$();\n\n this.show(left, $(window).scrollTop() + top - $this.outerHeight() - 5);\n }\n\n showEnd(right, bottom) {\n const $this = this.$();\n\n this.show(right - $this.outerWidth(), $(window).scrollTop() + bottom + 5);\n }\n\n hide() {\n this.$().hide();\n $(document).off('mouseup', this.hideHandler);\n }\n}\n","import { extend } from 'flarum/extend';\nimport CommentPost from 'flarum/components/CommentPost';\n\nimport PostQuoteButton from './fragments/PostQuoteButton';\nimport selectedText from './utils/selectedText';\n\nexport default function addPostQuoteButton() {\n extend(CommentPost.prototype, 'oncreate', function() {\n const post = this.attrs.post;\n\n if (post.isHidden() || (app.session.user && !post.discussion().canReply())) return;\n\n const $postBody = this.$('.Post-body');\n\n // Wrap the quote button in a wrapper element so that we can render\n // button into it.\n const $container = $('');\n\n const button = new PostQuoteButton(post);\n\n const handler = function(e) {\n setTimeout(() => {\n const content = selectedText($postBody);\n if (content) {\n button.content = content;\n m.render($container[0], button.render());\n\n const rects = window.getSelection().getRangeAt(0).getClientRects();\n const firstRect = rects[0];\n\n if (e.clientY < firstRect.bottom && e.clientX - firstRect.right < firstRect.left - e.clientX) {\n button.showStart(firstRect.left, firstRect.top);\n } else {\n const lastRect = rects[rects.length - 1];\n button.showEnd(lastRect.right, lastRect.bottom);\n }\n }\n }, 1);\n };\n\n this.$().after($container).on('mouseup', handler);\n\n if ('ontouchstart' in window) {\n document.addEventListener('selectionchange', handler, false);\n }\n });\n}\n","/**\n * Finds the selected text in the provided composer body.\n */\nexport default function selectedText(body) {\n const selection = window.getSelection();\n\n if (selection?.rangeCount) {\n const range = selection.getRangeAt(0);\n const parent = range.commonAncestorContainer;\n\n if (body[0] === parent || $.contains(body[0], parent)) {\n const clone = $('
').append(range.cloneContents());\n\n // Replace emoji images with their shortcode (found in alt attribute)\n clone.find('img.emoji').replaceWith(function () {\n return this.alt;\n });\n\n // Replace all other images with a Markdown image\n clone.find('img').replaceWith(function () {\n return `![](${this.src})`;\n });\n\n // Replace all links with a Markdown link\n clone.find('a').replaceWith(function () {\n return `[${this.innerText}](${this.href})`;\n });\n\n return clone.text();\n }\n }\n return '';\n}\n","import Fragment from 'flarum/Fragment';\n\nexport default class AutocompleteDropdown extends Fragment {\n items = [];\n active = false;\n index = 0;\n keyWasJustPressed = false;\n\n view() {\n return (\n
\n {this.items.map(item =>
{item}
)}\n
\n );\n }\n\n show(left, top) {\n this.$().show().css({\n left: left + 'px',\n top: top + 'px'\n });\n this.active = true;\n }\n\n hide() {\n this.$().hide();\n this.active = false;\n }\n\n navigate(delta) {\n this.keyWasJustPressed = true;\n this.setIndex(this.index + delta, true);\n clearTimeout(this.keyWasJustPressedTimeout);\n this.keyWasJustPressedTimeout = setTimeout(() => this.keyWasJustPressed = false, 500);\n }\n\n complete() {\n this.$('li').eq(this.index).find('button').click();\n }\n\n setIndex(index, scrollToItem) {\n if (this.keyWasJustPressed && !scrollToItem) return;\n\n const $dropdown = this.$();\n const $items = $dropdown.find('li');\n let rangedIndex = index;\n\n if (rangedIndex < 0) {\n rangedIndex = $items.length - 1;\n } else if (rangedIndex >= $items.length) {\n rangedIndex = 0;\n }\n\n this.index = rangedIndex;\n\n const $item = $items.removeClass('active').eq(rangedIndex).addClass('active');\n\n if (scrollToItem) {\n const dropdownScroll = $dropdown.scrollTop();\n const dropdownTop = $dropdown.offset().top;\n const dropdownBottom = dropdownTop + $dropdown.outerHeight();\n const itemTop = $item.offset().top;\n const itemBottom = itemTop + $item.outerHeight();\n\n let scrollTop;\n if (itemTop < dropdownTop) {\n scrollTop = dropdownScroll - dropdownTop + itemTop - parseInt($dropdown.css('padding-top'), 10);\n } else if (itemBottom > dropdownBottom) {\n scrollTop = dropdownScroll - dropdownBottom + itemBottom + parseInt($dropdown.css('padding-bottom'), 10);\n }\n\n if (typeof scrollTop !== 'undefined') {\n $dropdown.stop(true).animate({ scrollTop }, 100);\n }\n }\n }\n}\n","import { extend } from 'flarum/common/extend';\nimport TextEditor from 'flarum/common/components/TextEditor';\nimport TextEditorButton from 'flarum/common/components/TextEditorButton';\nimport ReplyComposer from 'flarum/forum/components/ReplyComposer';\nimport EditPostComposer from 'flarum/forum/components/EditPostComposer';\nimport avatar from 'flarum/common/helpers/avatar';\nimport usernameHelper from 'flarum/common/helpers/username';\nimport highlight from 'flarum/common/helpers/highlight';\nimport KeyboardNavigatable from 'flarum/forum/utils/KeyboardNavigatable';\nimport { truncate } from 'flarum/common/utils/string';\nimport { throttle } from 'flarum/common/utils/throttleDebounce';\n\nimport AutocompleteDropdown from './fragments/AutocompleteDropdown';\nimport getMentionText from './utils/getMentionText';\n\nconst throttledSearch = throttle(\n 250, // 250ms timeout\n function (typed, searched, returnedUsers, returnedUserIds, dropdown, buildSuggestions) {\n const typedLower = typed.toLowerCase();\n if (!searched.includes(typedLower)) {\n app.store.find('users', { filter: { q: typed }, page: { limit: 5 } }).then((results) => {\n results.forEach((u) => {\n if (!returnedUserIds.has(u.id())) {\n returnedUserIds.add(u.id());\n returnedUsers.push(u);\n }\n });\n \n buildSuggestions();\n });\n searched.push(typedLower);\n }\n }\n);\n\nexport default function addComposerAutocomplete() {\n const $container = $('');\n const dropdown = new AutocompleteDropdown();\n\n extend(TextEditor.prototype, 'oncreate', function () {\n const $editor = this.$('.TextEditor-editor').wrap('');\n\n this.navigator = new KeyboardNavigatable();\n this.navigator\n .when(() => dropdown.active)\n .onUp(() => dropdown.navigate(-1))\n .onDown(() => dropdown.navigate(1))\n .onSelect(dropdown.complete.bind(dropdown))\n .onCancel(dropdown.hide.bind(dropdown))\n .bindTo($editor);\n\n $editor.after($container);\n });\n\n extend(TextEditor.prototype, 'buildEditorParams', function (params) {\n const searched = [];\n let relMentionStart;\n let absMentionStart;\n let typed;\n let matchTyped;\n\n // We store users returned from an API here to preserve order in which they are returned\n // This prevents the user list jumping around while users are returned.\n // We also use a hashset for user IDs to provide O(1) lookup for the users already in the list.\n const returnedUsers = Array.from(app.store.all('users'));\n const returnedUserIds = new Set(returnedUsers.map((u) => u.id()));\n\n const applySuggestion = (replacement) => {\n app.composer.editor.replaceBeforeCursor(absMentionStart - 1, replacement + ' ');\n\n dropdown.hide();\n };\n\n params.inputListeners.push(function () {\n const selection = app.composer.editor.getSelectionRange();\n\n const cursor = selection[0];\n\n if (selection[1] - cursor > 0) return;\n\n // Search backwards from the cursor for an '@' symbol. If we find one,\n // we will want to show the autocomplete dropdown!\n const lastChunk = app.composer.editor.getLastNChars(30);\n absMentionStart = 0;\n for (let i = lastChunk.length - 1; i >= 0; i--) {\n const character = lastChunk.substr(i, 1);\n if (character === '@' && (i == 0 || /\\s/.test(lastChunk.substr(i - 1, 1)))) {\n relMentionStart = i + 1;\n absMentionStart = cursor - lastChunk.length + i + 1;\n break;\n }\n }\n\n dropdown.hide();\n dropdown.active = false;\n\n if (absMentionStart) {\n typed = lastChunk.substring(relMentionStart).toLowerCase();\n matchTyped = typed.match(/^[\"|“]((?:(?!\"#).)+)$/);\n typed = (matchTyped && matchTyped[1]) || typed;\n\n const makeSuggestion = function (user, replacement, content, className = '') {\n const username = usernameHelper(user);\n\n if (typed) {\n username.children = [highlight(username.text, typed)];\n delete username.text;\n }\n\n return (\n \n );\n };\n\n const userMatches = function (user) {\n const names = [user.username(), user.displayName()];\n\n return names.some((name) => name.toLowerCase().substr(0, typed.length) === typed);\n };\n\n const buildSuggestions = () => {\n const suggestions = [];\n\n // If the user has started to type a username, then suggest users\n // matching that username.\n if (typed) {\n returnedUsers.forEach((user) => {\n if (!userMatches(user)) return;\n\n suggestions.push(makeSuggestion(user, getMentionText(user), '', 'MentionsDropdown-user'));\n });\n }\n\n // If the user is replying to a discussion, or if they are editing a\n // post, then we can suggest other posts in the discussion to mention.\n // We will add the 5 most recent comments in the discussion which\n // match any username characters that have been typed.\n if (app.composer.bodyMatches(ReplyComposer) || app.composer.bodyMatches(EditPostComposer)) {\n const composerAttrs = app.composer.body.attrs;\n const composerPost = composerAttrs.post;\n const discussion = (composerPost && composerPost.discussion()) || composerAttrs.discussion;\n\n if (discussion) {\n discussion\n .posts()\n // Filter to only comment posts, and replies before this message\n .filter((post) => post && post.contentType() === 'comment' && (!composerPost || post.number() < composerPost.number()))\n // Sort by new to old\n .sort((a, b) => b.createdAt() - a.createdAt())\n // Filter to where the user matches what is being typed\n .filter((post) => {\n const user = post.user();\n return user && userMatches(user);\n })\n // Get the first 5\n .splice(0, 5)\n // Make the suggestions\n .forEach((post) => {\n const user = post.user();\n suggestions.push(\n makeSuggestion(\n user,\n getMentionText(user, post.id()),\n [\n app.translator.trans('flarum-mentions.forum.composer.reply_to_post_text', { number: post.number() }),\n ' — ',\n truncate(post.contentPlain(), 200),\n ],\n 'MentionsDropdown-post'\n )\n );\n });\n }\n }\n\n if (suggestions.length) {\n dropdown.items = suggestions;\n m.render($container[0], dropdown.render());\n\n dropdown.show();\n const coordinates = app.composer.editor.getCaretCoordinates(absMentionStart);\n const width = dropdown.$().outerWidth();\n const height = dropdown.$().outerHeight();\n const parent = dropdown.$().offsetParent();\n let left = coordinates.left;\n let top = coordinates.top + 15;\n\n // Keep the dropdown inside the editor.\n if (top + height > parent.height()) {\n top = coordinates.top - height - 15;\n }\n if (left + width > parent.width()) {\n left = parent.width() - width;\n }\n\n // Prevent the dropdown from going off screen on mobile\n top = Math.max(-(parent.offset().top - $(document).scrollTop()), top);\n left = Math.max(-parent.offset().left, left);\n\n dropdown.show(left, top);\n } else {\n dropdown.active = false;\n dropdown.hide();\n }\n };\n\n dropdown.active = true;\n\n buildSuggestions();\n\n dropdown.setIndex(0);\n dropdown.$().scrollTop(0);\n\n // Don't send API calls searching for users until at least 2 characters have been typed.\n // This focuses the mention results on users and posts in the discussion.\n if (typed.length > 1) {\n throttledSearch(typed, searched, returnedUsers, returnedUserIds, dropdown, buildSuggestions);\n }\n }\n });\n });\n\n extend(TextEditor.prototype, 'toolbarItems', function (items) {\n items.add(\n 'mention',\n this.attrs.composer.editor.insertAtCursor(' @')} icon=\"fas fa-at\">\n {app.translator.trans('flarum-mentions.forum.composer.mention_tooltip')}\n \n );\n });\n}\n","import Notification from 'flarum/components/Notification';\nimport { truncate } from 'flarum/utils/string';\n\nexport default class PostMentionedNotification extends Notification {\n icon() {\n return 'fas fa-reply';\n }\n\n href() {\n const notification = this.attrs.notification;\n const post = notification.subject();\n const content = notification.content();\n\n return app.route.discussion(post.discussion(), content && content.replyNumber);\n }\n\n content() {\n const notification = this.attrs.notification;\n const user = notification.fromUser();\n\n return app.translator.trans('flarum-mentions.forum.notifications.post_mentioned_text', {user, count: 1});\n }\n\n excerpt() {\n return truncate(this.attrs.notification.subject().contentPlain(), 200);\n }\n}\n","import Notification from 'flarum/components/Notification';\nimport { truncate } from 'flarum/utils/string';\n\nexport default class UserMentionedNotification extends Notification {\n icon() {\n return 'fas fa-at';\n }\n\n href() {\n const post = this.attrs.notification.subject();\n\n return app.route.discussion(post.discussion(), post.number());\n }\n\n content() {\n const user = this.attrs.notification.fromUser();\n\n return app.translator.trans('flarum-mentions.forum.notifications.user_mentioned_text', {user});\n }\n\n excerpt() {\n return truncate(this.attrs.notification.subject().contentPlain(), 200);\n }\n}\n","import PostsUserPage from 'flarum/components/PostsUserPage';\n\n/**\n * The `MentionsUserPage` component shows post which user Mentioned at\n */\nexport default class MentionsUserPage extends PostsUserPage {\n /**\n * Load a new page of the user's activity feed.\n *\n * @param {Integer} [offset] The position to start getting results from.\n * @return {Promise}\n * @protected\n */\n loadResults(offset) {\n return app.store.find('posts', {\n filter: {\n type: 'comment',\n mentioned: this.user.id()\n },\n page: {offset, limit: this.loadLimit},\n sort: '-createdAt'\n });\n }\n}\n","import username from 'flarum/helpers/username';\nimport extractText from 'flarum/utils/extractText';\n\nexport function filterUserMentions(tag) {\n let user;\n\n if (app.forum.attribute('allowUsernameMentionFormat') && tag.hasAttribute('username'))\n user = app.store.getBy('users', 'username', tag.getAttribute('username'));\n else if (tag.hasAttribute('id'))\n user = app.store.getById('users', tag.getAttribute('id'));\n\n if (user) {\n tag.setAttribute('id', user.id());\n tag.setAttribute('slug', user.slug());\n tag.setAttribute('displayname', extractText(username(user)));\n\n return true;\n }\n\n tag.invalidate();\n}\n\nexport function filterPostMentions(tag) {\n const post = app.store.getById('posts', tag.getAttribute('id'));\n\n if (post) {\n tag.setAttribute('discussionid', post.discussion().id());\n tag.setAttribute('number', post.number());\n tag.setAttribute('displayname', extractText(username(post.user())));\n\n return true;\n }\n}\n","import { extend } from 'flarum/extend';\nimport app from 'flarum/app';\nimport NotificationGrid from 'flarum/components/NotificationGrid';\nimport { getPlainContent } from 'flarum/utils/string';\n\nimport addPostMentionPreviews from './addPostMentionPreviews';\nimport addMentionedByList from './addMentionedByList';\nimport addPostReplyAction from './addPostReplyAction';\nimport addPostQuoteButton from './addPostQuoteButton';\nimport addComposerAutocomplete from './addComposerAutocomplete';\nimport PostMentionedNotification from './components/PostMentionedNotification';\nimport UserMentionedNotification from './components/UserMentionedNotification';\nimport UserPage from 'flarum/components/UserPage'\nimport LinkButton from 'flarum/components/LinkButton';\nimport MentionsUserPage from './components/MentionsUserPage';\n\napp.initializers.add('flarum-mentions', function() {\n // For every mention of a post inside a post's content, set up a hover handler\n // that shows a preview of the mentioned post.\n addPostMentionPreviews();\n\n // In the footer of each post, show information about who has replied (i.e.\n // who the post has been mentioned by).\n addMentionedByList();\n\n // Add a 'reply' control to the footer of each post. When clicked, it will\n // open up the composer and add a post mention to its contents.\n addPostReplyAction();\n\n // Show a Quote button when Post text is selected\n addPostQuoteButton();\n\n // After typing '@' in the composer, show a dropdown suggesting a bunch of\n // posts or users that the user could mention.\n addComposerAutocomplete();\n\n app.notificationComponents.postMentioned = PostMentionedNotification;\n app.notificationComponents.userMentioned = UserMentionedNotification;\n\n // Add notification preferences.\n extend(NotificationGrid.prototype, 'notificationTypes', function(items) {\n items.add('postMentioned', {\n name: 'postMentioned',\n icon: 'fas fa-reply',\n label: app.translator.trans('flarum-mentions.forum.settings.notify_post_mentioned_label')\n });\n\n items.add('userMentioned', {\n name: 'userMentioned',\n icon: 'fas fa-at',\n label: app.translator.trans('flarum-mentions.forum.settings.notify_user_mentioned_label')\n });\n });\n\n // Add mentions tab in user profile\n app.routes['user.mentions'] = {path: '/u/:username/mentions', component: MentionsUserPage};\n extend(UserPage.prototype, 'navItems', function(items) {\n const user = this.user;\n items.add('mentions',\n LinkButton.component({\n href: app.route('user.mentions', {username: user.slug()}),\n name: 'mentions',\n icon: 'fas fa-at'\n }, app.translator.trans('flarum-mentions.forum.user.mentions_link')),\n 80\n );\n });\n\n // Remove post mentions when rendering post previews.\n getPlainContent.removeSelectors.push('a.PostMention');\n});\n\nexport * from './utils/textFormatter';\n","import { extend } from 'flarum/common/extend';\nimport CommentPost from 'flarum/forum/components/CommentPost';\nimport PostPreview from 'flarum/forum/components/PostPreview';\nimport LoadingIndicator from 'flarum/common/components/LoadingIndicator';\n\nexport default function addPostMentionPreviews() {\n function addPreviews() {\n const contentHtml = this.attrs.post.contentHtml();\n\n if (contentHtml === this.oldPostContentHtml || this.isEditing()) return;\n\n this.oldPostContentHtml = contentHtml;\n\n const parentPost = this.attrs.post;\n const $parentPost = this.$();\n\n this.$().on('click', '.UserMention:not(.UserMention--deleted), .PostMention:not(.PostMention--deleted)', function (e) {\n m.route.set(this.getAttribute('href'));\n e.preventDefault();\n });\n\n this.$('.PostMention:not(.PostMention--deleted)').each(function () {\n const $this = $(this);\n const id = $this.data('id');\n let timeout;\n\n // Wrap the mention link in a wrapper element so that we can insert a\n // preview popup as its sibling and relatively position it.\n const $preview = $('
');\n $parentPost.append($preview);\n\n const getPostElement = () => {\n return $(`.PostStream-item[data-id=\"${id}\"]`);\n };\n\n const showPreview = () => {\n // When the user hovers their mouse over the mention, look for the\n // post that it's referring to in the stream, and determine if it's\n // in the viewport. If it is, we will \"pulsate\" it.\n const $post = getPostElement();\n let visible = false;\n if ($post.length) {\n const top = $post.offset().top;\n const scrollTop = window.pageYOffset;\n if (top > scrollTop && top + $post.height() < scrollTop + $(window).height()) {\n $post.addClass('pulsate');\n visible = true;\n }\n }\n\n // Otherwise, we will show a popup preview of the post. If the post\n // hasn't yet been loaded, we will need to do that.\n if (!visible) {\n // Position the preview so that it appears above the mention.\n // (The offsetParent should be .Post-body.)\n const positionPreview = () => {\n const previewHeight = $preview.outerHeight(true);\n let offset = 0;\n\n // If the preview goes off the top of the viewport, reposition it to\n // be below the mention.\n if ($this.offset().top - previewHeight < $(window).scrollTop() + $('#header').outerHeight()) {\n offset += $this.outerHeight(true);\n } else {\n offset -= previewHeight;\n }\n\n $preview\n .show()\n .css('top', $this.offset().top - $parentPost.offset().top + offset)\n .css('left', $this.offsetParent().offset().left - $parentPost.offset().left)\n .css('max-width', $this.offsetParent().width());\n };\n\n const showPost = (post) => {\n const discussion = post.discussion();\n\n m.render($preview[0], [\n discussion !== parentPost.discussion() ? (\n
\n {discussion.title()}\n
\n ) : (\n ''\n ),\n
{PostPreview.component({ post })}
,\n ]);\n positionPreview();\n };\n\n const post = app.store.getById('posts', id);\n if (post && post.discussion()) {\n showPost(post);\n } else {\n m.render($preview[0], LoadingIndicator.component());\n app.store.find('posts', id).then(showPost);\n positionPreview();\n }\n\n setTimeout(() => $preview.off('transitionend').addClass('in'));\n }\n };\n\n const hidePreview = () => {\n getPostElement().removeClass('pulsate');\n if ($preview.hasClass('in')) {\n $preview.removeClass('in').one('transitionend', () => $preview.hide());\n }\n };\n\n // On a touch (mobile) device we cannot hover the link to reveal the preview.\n // Instead we cancel the navigation so that a click reveals the preview.\n // Users can then click on the preview to go to the post if desired.\n $this.on('touchend', (e) => {\n if (e.cancelable) {\n e.preventDefault();\n }\n });\n\n $this\n .add($preview)\n .hover(\n () => {\n clearTimeout(timeout);\n timeout = setTimeout(showPreview, 250);\n },\n () => {\n clearTimeout(timeout);\n getPostElement().removeClass('pulsate');\n timeout = setTimeout(hidePreview, 250);\n }\n )\n .on('touchend', (e) => {\n showPreview();\n e.stopPropagation();\n });\n\n $(document).on('touchend', hidePreview);\n });\n }\n\n extend(CommentPost.prototype, 'oncreate', addPreviews);\n extend(CommentPost.prototype, 'onupdate', addPreviews);\n}\n","import { extend } from 'flarum/common/extend';\nimport Model from 'flarum/common/Model';\nimport Post from 'flarum/common/models/Post';\nimport CommentPost from 'flarum/forum/components/CommentPost';\nimport Link from 'flarum/common/components/Link';\nimport PostPreview from 'flarum/forum/components/PostPreview';\nimport punctuateSeries from 'flarum/common/helpers/punctuateSeries';\nimport username from 'flarum/common/helpers/username';\nimport icon from 'flarum/common/helpers/icon';\n\nexport default function addMentionedByList() {\n Post.prototype.mentionedBy = Model.hasMany('mentionedBy');\n\n function hidePreview() {\n this.$('.Post-mentionedBy-preview')\n .removeClass('in')\n .one('transitionend', function () {\n $(this).hide();\n });\n }\n\n extend(CommentPost.prototype, 'oncreate', function () {\n let timeout;\n const post = this.attrs.post;\n const replies = post.mentionedBy();\n\n if (replies && replies.length) {\n const $preview = $('
');\n this.$().append($preview);\n\n const $parentPost = this.$();\n const $this = this.$('.Post-mentionedBy');\n\n const showPreview = () => {\n if (!$preview.hasClass('in') && $preview.is(':visible')) return;\n\n // When the user hovers their mouse over the list of people who have\n // replied to the post, render a list of reply previews into a\n // popup.\n m.render(\n $preview[0],\n replies.map((reply) => (\n
\n ))\n );\n\n $preview\n .show()\n .css('top', $this.offset().top - $parentPost.offset().top + $this.outerHeight(true))\n .css('left', $this.offsetParent().offset().left - $parentPost.offset().left)\n .css('max-width', $parentPost.width());\n\n setTimeout(() => $preview.off('transitionend').addClass('in'));\n };\n\n $this.add($preview).hover(\n () => {\n clearTimeout(timeout);\n timeout = setTimeout(showPreview, 250);\n },\n () => {\n clearTimeout(timeout);\n timeout = setTimeout(hidePreview, 250);\n }\n );\n\n // Whenever the user hovers their mouse over a particular name in the\n // list of repliers, highlight the corresponding post in the preview\n // popup.\n this.$()\n .find('.Post-mentionedBy-summary a')\n .hover(\n function () {\n $preview.find('[data-number=\"' + $(this).data('number') + '\"]').addClass('active');\n },\n function () {\n $preview.find('[data-number]').removeClass('active');\n }\n );\n }\n });\n\n extend(CommentPost.prototype, 'footerItems', function (items) {\n const post = this.attrs.post;\n const replies = post.mentionedBy();\n\n if (replies && replies.length) {\n const users = [];\n const repliers = replies\n .sort((reply) => (reply.user() === app.session.user ? -1 : 0))\n .filter((reply) => {\n const user = reply.user();\n if (users.indexOf(user) === -1) {\n users.push(user);\n return true;\n }\n });\n\n const limit = 4;\n const overLimit = repliers.length > limit;\n\n // Create a list of unique users who have replied. So even if a user has\n // replied twice, they will only be in this array once.\n const names = repliers.slice(0, overLimit ? limit - 1 : limit).map((reply) => {\n const user = reply.user();\n\n return (\n \n {app.session.user === user ? app.translator.trans('flarum-mentions.forum.post.you_text') : username(user)}\n \n );\n });\n\n // If there are more users that we've run out of room to display, add a \"x\n // others\" name to the end of the list. Clicking on it will display a modal\n // with a full list of names.\n if (overLimit) {\n const count = repliers.length - names.length;\n\n names.push(app.translator.trans('flarum-mentions.forum.post.others_text', { count }));\n }\n\n items.add(\n 'replies',\n
\n );\n }\n });\n}\n","import { extend } from 'flarum/extend';\nimport Button from 'flarum/components/Button';\nimport CommentPost from 'flarum/components/CommentPost';\n\nimport reply from './utils/reply';\n\nexport default function () {\n extend(CommentPost.prototype, 'actionItems', function (items) {\n\n const post = this.attrs.post;\n\n if (post.isHidden() || (app.session.user && !post.discussion().canReply())) return;\n\n items.add('reply',\n \n );\n });\n}\n"],"sourceRoot":""}
\ No newline at end of file