nodebb-theme-persona 14.0.15 → 14.0.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodebb-theme-persona",
3
- "version": "14.0.15",
3
+ "version": "14.0.17",
4
4
  "nbbpm": {
5
5
  "compatibility": "^4.0.0"
6
6
  },
@@ -19,7 +19,7 @@ define('persona/mobile-menu', [
19
19
  if (!menuEl || !chatsMenuEl) {
20
20
  return;
21
21
  }
22
- const chatMenuVisible = app.user && parseInt(app.user.uid, 10);
22
+ const chatMenuVisible = app.user && app.user.userslug;
23
23
  let swapped = !!Storage.getItem('persona:menus:legacy-layout');
24
24
  const margin = window.innerWidth;
25
25
 
@@ -118,7 +118,7 @@ define('persona/mobile-menu', [
118
118
  $('#user-control-list').children().clone(true, true).appendTo($('#chats-menu [data-section="profile"] ul'));
119
119
 
120
120
  socket.on('event:user_status_change', function (data) {
121
- if (parseInt(data.uid, 10) === app.user.uid) {
121
+ if (String(data.uid) === String(app.user.uid)) {
122
122
  app.updateUserStatus($('#chats-menu [component="user/status"]'), data.status);
123
123
  navSlideout.close();
124
124
  }
package/public/persona.js CHANGED
@@ -166,35 +166,30 @@ $(document).ready(function () {
166
166
  function generateUserCard(ev) {
167
167
  var avatar = $(this);
168
168
  var uid = avatar.parents('[data-uid]').attr('data-uid');
169
- var data = (ajaxify.data.topics || ajaxify.data.posts);
170
-
171
- for (var i = 0, ii = data.length; i < ii; i++) {
172
- if (parseInt(data[i].uid, 10) === parseInt(uid, 10)) {
173
- data = data[i].user;
174
- break;
175
- }
176
- }
169
+ const topicOrPost = (ajaxify.data.topics || ajaxify.data.posts || []).find(d => String(d.uid) === String(uid));
170
+ if (!topicOrPost) return;
171
+ const user = topicOrPost.user;
177
172
 
178
173
  $('.persona-usercard').remove();
179
174
 
180
- if (parseInt(data.uid, 10) === 0) {
175
+ if (!user.userslug) {
181
176
  return false;
182
177
  }
183
178
 
184
- socket.emit('user.isFollowing', { uid: data.uid }, function (err, isFollowing) {
179
+ socket.emit('user.isFollowing', { uid: user.uid }, function (err, isFollowing) {
185
180
  if (err) {
186
181
  return err;
187
182
  }
188
183
 
189
- app.parseAndTranslate('modules/usercard', data, function (html) {
184
+ app.parseAndTranslate('modules/usercard', user, function (html) {
190
185
  var card = $(html);
191
186
  avatar.parents('a').after(card.hide());
192
187
 
193
- if (parseInt(app.user.uid, 10) === parseInt(data.uid, 10) || !app.user.uid) {
188
+ if (String(app.user.uid) === String(user.uid) || !app.user.uid) {
194
189
  card.find('.btn-morph').hide();
195
190
  } else {
196
- const uid = isFinite(data.uid) ? data.uid : encodeURIComponent(data.userslug);
197
- setupFavouriteMorph(card, uid, data.username);
191
+ const uid = isFinite(user.uid) ? user.uid : encodeURIComponent(user.userslug);
192
+ setupFavouriteMorph(card, uid, user.username);
198
193
 
199
194
  if (isFollowing) {
200
195
  $('.btn-morph').addClass('heart');
package/scss/account.scss CHANGED
@@ -13,14 +13,6 @@
13
13
  > .row {
14
14
  margin-left: auto;
15
15
  margin-right: auto;
16
-
17
- .fullname {
18
- text-align: center;
19
- font-size: 20px;
20
- color: $gray-600;
21
- font-weight: 300;
22
- margin-bottom: 24px;
23
- }
24
16
  }
25
17
 
26
18
  .cover {
@@ -188,51 +180,6 @@
188
180
  margin-bottom: 12px;
189
181
  font-size: 32px;
190
182
  }
191
-
192
- .username {
193
- text-transform: uppercase;
194
- text-align: center;
195
- margin-top: 0px;
196
- font-size: 15px;
197
- }
198
-
199
- .aboutme > p {
200
- max-width: 75%;
201
- margin-left: auto;
202
- margin-right: auto;
203
- color: $gray-600;
204
- }
205
-
206
- .profile-meta {
207
- font-size: 10px;
208
- text-transform: uppercase;
209
- color: #777;
210
- margin-top: 25px;
211
-
212
- strong {
213
- color: #333;
214
- }
215
- }
216
-
217
- .account-stats {
218
- text-align: center;
219
- font-size: 35px;
220
- line-height: 25px;
221
- margin-top: 25px;
222
- margin-bottom: -20px;
223
-
224
- .stat {
225
- display: inline-block;
226
- min-width: 100px;
227
- margin-bottom: 20px;
228
- }
229
-
230
- .stat-label {
231
- font-size: 12px;
232
- text-transform: uppercase;
233
- color: $gray-600;
234
- }
235
- }
236
183
  }
237
184
 
238
185
  .show-success {
package/scss/mixins.scss CHANGED
@@ -21,7 +21,7 @@
21
21
  // Opaque ring
22
22
  position: relative;
23
23
  z-index: 1;
24
- box-shadow: 0 0 0 ($spacer * .5) var(--bs-body-bg);
24
+ box-shadow: 0 0 0 4px var(--bs-body-bg);
25
25
  }
26
26
 
27
27
  [component="user/locality"] {
package/scss/persona.scss CHANGED
@@ -28,3 +28,5 @@
28
28
  @import "modules/composer";
29
29
  @import "modules/user-menu";
30
30
  @import "modules/topics-list";
31
+
32
+ @import "skins";
@@ -3,7 +3,6 @@
3
3
 
4
4
  .posts-list-item {
5
5
  width: 100%;
6
- margin-bottom: 0px;
7
6
 
8
7
  &.deleted {
9
8
  -moz-opacity: 0.30;
@@ -29,28 +28,11 @@
29
28
  }
30
29
 
31
30
  .topic-title {
32
- color: $gray-800;
33
31
  font-weight: 900;
34
32
  font-size: 125%;
35
33
  text-decoration: underline;
36
34
  }
37
35
 
38
- .topic-category {
39
- text-transform: uppercase;
40
- font-size: 10px;
41
- color: $gray-600;
42
- margin-top: 6px;
43
- margin-right: 10px;
44
- margin-bottom: 25px;
45
- display: inline-block;
46
- margin-top: 10px;
47
-
48
- a {
49
- font-weight: 900;
50
- color: $gray-600;
51
- }
52
- }
53
-
54
36
  .content {
55
37
  max-height: 240px;
56
38
  position: relative;
@@ -102,15 +84,10 @@
102
84
  .post-author {
103
85
  padding-left: 25px;
104
86
  margin-top: -14px;
105
- color: $gray-600;
106
87
 
107
88
  a {
108
- color: $gray-600;
109
89
  font-weight: 900;
110
-
111
90
  }
112
-
113
- text-transform: uppercase;
114
91
  }
115
92
  }
116
93
  }
@@ -0,0 +1,64 @@
1
+ .skin-quartz {
2
+ // $body-bg-image is gradient in quartz
3
+ [component="post"] {
4
+ .icon {
5
+ background-color: transparent !important;
6
+ .avatar {
7
+ box-shadow: none!important;
8
+ }
9
+ }
10
+ .timeline-badge {
11
+ box-shadow: none!important;
12
+ }
13
+ }
14
+ .form-control::placeholder {
15
+ color:$gray-100!important;
16
+ }
17
+ .topic-header {
18
+ background-color: transparent!important;
19
+ backdrop-filter: blur(5px);
20
+ }
21
+ }
22
+
23
+ .skin-solar {
24
+ .form-control::placeholder {
25
+ color:$gray-100!important;
26
+ }
27
+ }
28
+
29
+ .skin-yeti {
30
+ .badge {
31
+ padding-left: 0.5rem;
32
+ padding-right: 0.5rem;
33
+ }
34
+ }
35
+
36
+ // table color fix, remove once https://github.com/thomaspark/bootswatch/issues/1276 is published
37
+ .skin-darkly, .skin-superhero, .skin-solar, .skin-quartz {
38
+ table > :not(caption) > * > * {
39
+ color: white;
40
+ }
41
+ }
42
+
43
+ .skin-superhero {
44
+ // fix read button in dropdowns
45
+ .mark-read .read {
46
+ color: $primary!important;
47
+ }
48
+ }
49
+
50
+ .skin-slate {
51
+ // fix unread button colors in dropdowns
52
+ .mark-read .unread {
53
+ color: $secondary!important;
54
+ }
55
+ }
56
+
57
+ :root {
58
+ .skin-darkly, .skin-slate, .skin-cyborg {
59
+ --bs-border-color: #929292;
60
+ }
61
+ .skin-zephyr {
62
+ --bs-secondary-rgb: var(--bs-secondary-color);
63
+ }
64
+ }
@@ -5,10 +5,7 @@
5
5
 
6
6
  .topic-list-header {
7
7
  top: calc(var(--panel-offset));
8
- background-color: $body-bg;
9
8
  z-index: $zindex-dropdown; // allows for top nav dropdowns to appear on top
10
- border-top: 1px solid $post-border-color;
11
- border-bottom: 1px solid $post-border-color;
12
9
  }
13
10
 
14
11
  .topic-list .title small {
@@ -1,9 +1,9 @@
1
1
  <!-- IMPORT partials/account/header.tpl -->
2
2
 
3
3
  <div class="profile row">
4
- <h1 class="fullname"><!-- IF fullname -->{fullname}<!-- ELSE -->{username}<!-- ENDIF fullname --></h1>
4
+ <h1 class="fullname text-center fs-2 text-secondary fw-light">{{{ if fullname }}}{fullname}{{{ else }}}{username}{{{ end }}}</h1>
5
5
  <div class="d-flex gap-2 justify-content-center mb-2" component="user/badges"></div>
6
- <h2 class="username"><!-- IF !banned -->@{username}<!-- ELSE -->[[user:banned]]<!-- ENDIF !banned --></h2>
6
+ <h2 class="username text-center fs-5"><!-- IF !banned -->@{username}<!-- ELSE -->[[user:banned]]<!-- ENDIF !banned --></h2>
7
7
  <!-- IF isAdminOrGlobalModeratorOrModerator -->
8
8
  <!-- IF banned -->
9
9
  <div class="text-center">
@@ -24,43 +24,42 @@
24
24
  <!-- ENDIF selectedGroup.slug -->
25
25
  {{{end}}}
26
26
  </div>
27
- <br/>
28
27
  <!-- ENDIF selectedGroup.length -->
29
28
 
30
29
  <!-- IF aboutme -->
31
- <span component="aboutme" class="text-center aboutme">{aboutmeParsed}</span>
30
+ <div component="aboutme" class="text-center aboutme text-secondary w-75 mx-auto text-center">{aboutmeParsed}</div>
32
31
  <!-- ENDIF aboutme -->
33
32
 
34
- <div class="account-stats">
33
+ <div class="account-stats fs-1 text-center mb-3">
35
34
  <!-- IF !reputation:disabled -->
36
- <div class="stat">
35
+ <div class="stat d-inline-block" style="min-width: 100px;">
37
36
  <div title="{reputation}">{humanReadableNumber(reputation)}</div>
38
- <span class="stat-label">[[global:reputation]]</span>
37
+ <div class="stat-label text-xs text-uppercase text-secondary">[[global:reputation]]</div>
39
38
  </div>
40
39
  <!-- ENDIF !reputation:disabled -->
41
40
 
42
- <div class="stat">
41
+ <div class="stat d-inline-block" style="min-width: 100px;">
43
42
  <div title="{profileviews}">{humanReadableNumber(profileviews)}</div>
44
- <span class="stat-label">[[user:profile-views]]</span>
43
+ <div class="stat-label text-xs text-uppercase text-secondary">[[user:profile-views]]</div>
45
44
  </div>
46
45
 
47
- <div class="stat">
46
+ <div class="stat d-inline-block" style="min-width: 100px;">
48
47
  <div><a title="{counts.posts}" href="{config.relative_path}/user/{userslug}/posts">{humanReadableNumber(counts.posts)}</a></div>
49
- <span class="stat-label">[[global:posts]]</span>
48
+ <div class="stat-label text-xs text-uppercase text-secondary">[[global:posts]]</div>
50
49
  </div>
51
50
 
52
- <div class="stat">
51
+ <div class="stat d-inline-block" style="min-width: 100px;">
53
52
  <div><a title="{counts.followers}" href="{config.relative_path}/user/{userslug}/followers">{humanReadableNumber(counts.followers)}</a></div>
54
- <span class="stat-label">[[user:followers]]</span>
53
+ <div class="stat-label text-xs text-uppercase text-secondary">[[user:followers]]</div>
55
54
  </div>
56
55
 
57
- <div class="stat">
56
+ <div class="stat d-inline-block" style="min-width: 100px;">
58
57
  <div><a title="{counts.following}" href="{config.relative_path}/user/{userslug}/following">{humanReadableNumber(counts.following)}</a></div>
59
- <span class="stat-label">[[user:following]]</span>
58
+ <div class="stat-label text-xs text-uppercase text-secondary">[[user:following]]</div>
60
59
  </div>
61
60
  </div>
62
61
 
63
- <div class="profile-meta d-flex gap-3 flex-wrap justify-content-center">
62
+ <div class="profile-meta text-xs text-uppercase d-flex gap-3 flex-wrap justify-content-center">
64
63
  <div class="w-100 d-flex gap-3 justify-content-center">
65
64
  <div>
66
65
  <span class="stat-label">[[user:joined]]</span>
@@ -81,8 +80,8 @@
81
80
  {{{ end }}}
82
81
 
83
82
  {{{ if age }}}
84
- <div>
85
- <span class="stat-label">[[user:age]]</span>
83
+ <div class="">
84
+ <span class="stat-label text-secondary ">[[user:age]]</span>
86
85
  <span class="fw-bold">{age}</span>
87
86
  </div>
88
87
  {{{ end }}}
@@ -9,7 +9,7 @@
9
9
  <!-- IMPORT partials/category/subcategory.tpl -->
10
10
 
11
11
  {{{ if (topics.length || privileges.topics:create) }}}
12
- <div class="topic-list-header sticky-top btn-toolbar justify-content-between align-items-center py-2 mb-2 flex-nowrap">
12
+ <div class="topic-list-header text-bg-light sticky-top btn-toolbar justify-content-between align-items-center p-1 mb-2 flex-nowrap">
13
13
  <div class="d-flex gap-1">
14
14
  {{{ if privileges.topics:create }}}
15
15
  <a href="{config.relative_path}/compose?cid={cid}" component="category/post" id="new_topic" class="btn btn-primary btn-sm text-nowrap" data-ajaxify="false" role="button">[[category:new-topic-button]]</a>
@@ -1,31 +1,33 @@
1
- <li component="post" class="posts-list-item row<!-- IF ../deleted --> deleted<!-- ELSE --><!-- IF ../topic.deleted --> deleted<!-- ENDIF --><!-- ENDIF -->{{{ if ../topic.scheduled }}} scheduled{{{ end }}}" data-pid="{../pid}" data-uid="{../uid}">
2
- <div class="col-lg-11 col-sm-10 col-9 post-body">
3
- <a class="topic-title" href="{config.relative_path}/post/{encodeURIComponent(../pid)}">
4
- <!-- IF !../isMainPost -->RE: <!-- ENDIF -->{../topic.title}
1
+ <li component="post" class="posts-list-item row {{{ if ./deleted }}} deleted{{{ else }}}{{{ if ./topic.deleted }}} deleted{{{ end }}}{{{ end }}}{{{ if ./topic.scheduled }}} scheduled{{{ end }}}" data-pid="{./pid}" data-uid="{./uid}">
2
+ <div class="col-lg-11 col-sm-10 col-9 post-body pb-3">
3
+ <a class="topic-title text-reset" href="{config.relative_path}/post/{encodeURIComponent(../pid)}">
4
+ {{{ if !./isMainPost }}}RE: {{{ end }}}{./topic.title}
5
5
  </a>
6
6
 
7
- <div component="post/content" class="content">
7
+ <div component="post/content" class="content mb-3">
8
8
  {../content}
9
9
  </div>
10
10
 
11
- <small class="topic-category"><a href="{config.relative_path}/category/{../category.slug}">[[global:posted-in, {../category.name}]]</a></small>
11
+ <div class="mb-3">
12
+ <a class="topic-category text-xs fw-bold text-uppercase text-secondary mb-3" href="{config.relative_path}/category/{../category.slug}">[[global:posted-in, {../category.name}]]</a>
12
13
 
13
- {{{ if ../isMainPost }}}
14
- {{{ if ../topic.tags.length }}}
15
- <span class="tag-list">
16
- {{{ each ../topic.tags }}}
17
- <a href="{config.relative_path}/tags/{topic.tags.valueEncoded}"><span class="tag tag-item tag-class-{topic.tags.class}">{topic.tags.valueEscaped}</span></a>
14
+ {{{ if ../isMainPost }}}
15
+ {{{ if ../topic.tags.length }}}
16
+ <span class="tag-list">
17
+ {{{ each ../topic.tags }}}
18
+ <a href="{config.relative_path}/tags/{topic.tags.valueEncoded}"><span class="tag tag-item tag-class-{topic.tags.class}">{topic.tags.valueEscaped}</span></a>
19
+ {{{ end }}}
20
+ </span>
18
21
  {{{ end }}}
19
- </span>
20
- {{{ end }}}
21
- {{{ end }}}
22
+ {{{ end }}}
23
+ </div>
22
24
 
23
25
  <div class="post-info">
24
- <a href="{config.relative_path}/user/{../user.userslug}">{buildAvatar(../user, "28px", true, "user-img not-responsive")}</a>
26
+ <a href="{config.relative_path}/user/{./user.userslug}">{buildAvatar(./user, "28px", true, "user-img not-responsive")}</a>
25
27
 
26
- <div class="post-author">
27
- <a href="{config.relative_path}/user/{../user.userslug}">{../user.displayname}</a><br />
28
- <span class="timeago" title="{../timestampISO}"></span>
28
+ <div class="post-author text-secondary text-uppercase">
29
+ <a class="text-reset" href="{config.relative_path}/user/{./user.userslug}">{./user.displayname}</a><br />
30
+ <span class="timeago" title="{./timestampISO}"></span>
29
31
  </div>
30
32
  </div>
31
33
  </div>
@@ -0,0 +1,5 @@
1
+ {{{ each thumbs }}}
2
+ <a class="d-inline-block" href="{./url}">
3
+ <img class="rounded-1 bg-light" style="width:auto; max-width: 4rem; height: 3.33rem;object-fit: contain;" src="{./url}" />
4
+ </a>
5
+ {{{ end }}}
@@ -54,7 +54,7 @@
54
54
  {function.buildCategoryLabel, ./category, "a", "border"}
55
55
  {{{ end }}}
56
56
 
57
- <span data-tid="{./tid}" component="topic/tags" class="lh-1 tag-list hidden-xs d-flex flex-wrap gap-1 {{{ if !./tags.length }}}hidden{{{ end }}}">
57
+ <span data-tid="{./tid}" component="topic/tags" class="lh-1 tag-list d-flex flex-wrap gap-1 {{{ if !./tags.length }}}hidden{{{ end }}}">
58
58
  {{{ each ./tags }}}
59
59
  <a href="{config.relative_path}/tags/{./valueEncoded}"><span class="badge border border-gray-300 fw-normal tag tag-class-{./class}" data-tag="{./value}">{./valueEscaped}</span></a>
60
60
  {{{ end }}}
@@ -5,7 +5,7 @@
5
5
  {{{end}}}
6
6
  </div>
7
7
  <div class="popular">
8
- <div class="topic-list-header sticky-top btn-toolbar justify-content-between align-items-center py-2 mb-2 gap-1">
8
+ <div class="topic-list-header text-bg-light sticky-top btn-toolbar justify-content-between align-items-center p-1 mb-2 gap-1">
9
9
  <div class="d-flex gap-1">
10
10
  {{{ if canPost }}}
11
11
  <!-- IMPORT partials/buttons/newTopic.tpl -->
@@ -5,7 +5,7 @@
5
5
  {{{end}}}
6
6
  </div>
7
7
  <div class="recent">
8
- <div class="topic-list-header sticky-top btn-toolbar justify-content-between align-items-between py-2 mb-2 gap-1">
8
+ <div class="topic-list-header text-bg-light sticky-top btn-toolbar justify-content-between align-items-between p-1 mb-2 gap-1">
9
9
  <div class="d-flex gap-1">
10
10
  {{{ if canPost }}}
11
11
  <!-- IMPORT partials/buttons/newTopic.tpl -->
package/templates/tag.tpl CHANGED
@@ -5,7 +5,7 @@
5
5
  {{{end}}}
6
6
  </div>
7
7
  <div class="tag">
8
- <div class="topic-list-header sticky-top btn-toolbar justify-content-between align-items-center py-2 mb-2 gap-1">
8
+ <div class="topic-list-header text-bg-light sticky-top btn-toolbar justify-content-between align-items-center p-1 mb-2 gap-1">
9
9
  <div class="d-flex gap-1">
10
10
  {{{ if loggedIn }}}
11
11
  <!-- IMPORT partials/buttons/newTopic.tpl -->
package/templates/top.tpl CHANGED
@@ -5,7 +5,7 @@
5
5
  {{{end}}}
6
6
  </div>
7
7
  <div class="top">
8
- <div class="topic-list-header sticky-top btn-toolbar justify-content-between align-items-center py-2 mb-2 gap-1">
8
+ <div class="topic-list-header text-bg-light sticky-top btn-toolbar justify-content-between align-items-center p-1 mb-2 gap-1">
9
9
  <div class="d-flex gap-1">
10
10
  {{{ if canPost }}}
11
11
  <!-- IMPORT partials/buttons/newTopic.tpl -->
@@ -16,7 +16,7 @@
16
16
  </div>
17
17
 
18
18
  <div class="topic-header sticky-top mb-3 bg-body">
19
- <div class="d-flex flex-wrap gap-3 border-bottom pb-2">
19
+ <div class="d-flex flex-wrap gap-3 border-bottom p-2">
20
20
  <div class="d-flex flex-column gap-2 flex-grow-1">
21
21
  <h1 component="post/header" class="mb-0" itemprop="name">
22
22
  <div class="topic-title d-flex">
@@ -56,13 +56,7 @@
56
56
  </div>
57
57
  </div>
58
58
  </div>
59
- <div class="d-flex flex-wrap gap-2 align-items-center hidden-empty" component="topic/thumb/list">
60
- {{{ each thumbs }}}
61
- <a class="d-inline-block" href="{./url}">
62
- <img class="rounded-1 bg-light" style="width:auto; max-width: 4rem; height: 3.33rem;object-fit: contain;" src="{./url}" />
63
- </a>
64
- {{{ end }}}
65
- </div>
59
+ <div class="d-flex flex-wrap gap-2 align-items-center hidden-empty" component="topic/thumb/list"><!-- IMPORT partials/topic/thumbs.tpl --></div>
66
60
  </div>
67
61
  </div>
68
62
  {{{ if merger }}}
@@ -5,7 +5,7 @@
5
5
  {{{end}}}
6
6
  </div>
7
7
  <div class="unread">
8
- <div class="topic-list-header sticky-top btn-toolbar justify-content-between align-items-center py-2 mb-2 gap-1">
8
+ <div class="topic-list-header text-bg-light sticky-top btn-toolbar justify-content-between align-items-center p-1 mb-2 gap-1">
9
9
  <div class="d-flex gap-1">
10
10
  <!-- IMPORT partials/buttons/newTopic.tpl -->
11
11
  <a href="{config.relative_path}/{selectedFilter.url}{querystring}" class="d-inline-block">
@@ -7,7 +7,7 @@
7
7
  <div class="row">
8
8
  <div class="world {{{if widgets.sidebar.length }}}col-lg-9 col-sm-12{{{ else }}}col-lg-12{{{ end }}}">
9
9
  {{{ if (topics.length || privileges.topics:create) }}}
10
- <div class="topic-list-header sticky-top btn-toolbar justify-content-between py-2 mb-2 flex-nowrap">
10
+ <div class="topic-list-header text-bg-light sticky-top btn-toolbar justify-content-between p-1 mb-2 gap-1 flex-nowrap">
11
11
  <div class="d-flex gap-1 align-items-stretch">
12
12
  {{{ if privileges.topics:create }}}
13
13
  <a href="{config.relative_path}/compose?cid={cid}" component="category/post" id="new_topic" class="btn btn-primary text-nowrap" data-ajaxify="false" role="button">[[category:new-topic-button]]</a>