nodebb-theme-harmony 0.0.14 → 1.0.0-beta.10

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-harmony",
3
- "version": "0.0.14",
3
+ "version": "1.0.0-beta.10",
4
4
  "nbbpm": {
5
5
  "compatibility": "^3.0.0"
6
6
  },
package/public/harmony.js CHANGED
@@ -1,6 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  $(document).ready(function () {
4
+ setupNProgress();
4
5
  setupMobileMenu();
5
6
  setupSearch();
6
7
  setupDrafts();
@@ -55,26 +56,6 @@ $(document).ready(function () {
55
56
  $('[component="sidebar/search"]').on('shown.bs.dropdown', function () {
56
57
  $(this).find('[component="search/fields"] input[name="query"]').trigger('focus');
57
58
  });
58
-
59
- function resizeResults(hookData) {
60
- if (hookData && hookData.data && !hookData.data.posts.length) {
61
- $('.bottombar .quick-search-results').css({ height: 'initial' });
62
- return;
63
- }
64
- const dropdown = $('.bottombar .search-dropdown');
65
- const padY = dropdown.innerHeight() - dropdown.height();
66
- const input = dropdown.find('.input-container').outerHeight(true);
67
- const showMore = dropdown.find('.show-more-container').outerHeight(true);
68
- const newHeight = Math.max(
69
- 150,
70
- $(window).height() - (input + (showMore || 0) + (padY * 2) + 30)
71
- );
72
- $('.bottombar .quick-search-results').height(newHeight);
73
- }
74
- require(['hooks'], function (hooks) {
75
- $(window).on('resize', resizeResults);
76
- hooks.on('action:search.quick.complete', resizeResults);
77
- });
78
59
  }
79
60
 
80
61
  function setupDrafts() {
@@ -122,4 +103,18 @@ $(document).ready(function () {
122
103
  updateBadgeCount();
123
104
  });
124
105
  }
106
+ function setupNProgress() {
107
+ require(['nprogress'], function (NProgress) {
108
+ window.nprogress = NProgress;
109
+ if (NProgress) {
110
+ $(window).on('action:ajaxify.start', function () {
111
+ NProgress.set(0.7);
112
+ });
113
+
114
+ $(window).on('action:ajaxify.end', function () {
115
+ NProgress.done(true);
116
+ });
117
+ }
118
+ });
119
+ }
125
120
  });
package/scss/chats.scss CHANGED
@@ -6,8 +6,10 @@
6
6
  body.page-user-chats {
7
7
  overflow: hidden;
8
8
  }
9
-
10
- .expanded-chat, .chat-modal {
9
+ [component="chat/nav-wrapper"] {
10
+ width: 300px;
11
+ }
12
+ .expanded-chat {
11
13
  // no taskbar so hide minimize button
12
14
  [data-action="minimize"] {
13
15
  display: none!important;
@@ -38,6 +40,9 @@ body.page-user-chats {
38
40
 
39
41
  /* Mobile handling of chat page */
40
42
  @include media-breakpoint-down(md) {
43
+ [component="chat/nav-wrapper"] {
44
+ width: 100%;
45
+ }
41
46
  .page-user-chats {
42
47
  .chats-full {
43
48
  padding-bottom: 8rem!important;
package/scss/harmony.scss CHANGED
@@ -19,5 +19,6 @@
19
19
  @import "modules/composer";
20
20
  @import "modules/topics-list";
21
21
  @import "modules/cover";
22
+ @import "modules/nprogress";
22
23
 
23
24
  @import "skins";
@@ -1,5 +1,5 @@
1
1
  .bottom-sheet {
2
- @include media-breakpoint-down(sm) {
2
+ @include media-breakpoint-down(md) {
3
3
  .dropdown-menu {
4
4
  display: block;
5
5
  visibility: hidden;
@@ -0,0 +1,80 @@
1
+ #nprogress {
2
+ pointer-events: none;
3
+ }
4
+
5
+ $nprogress-color: $primary;
6
+
7
+ #nprogress .bar {
8
+ background: $nprogress-color;
9
+ position: fixed;
10
+ z-index: 1031;
11
+ top: 0;
12
+ left: 0;
13
+ width: 100%;
14
+ height: 2px;
15
+ }
16
+
17
+ #nprogress .peg {
18
+ display: block;
19
+ position: absolute;
20
+ right: 0px;
21
+ width: 100px;
22
+ height: 100%;
23
+ box-shadow: 0 0 10px $nprogress-color, 0 0 5px $nprogress-color;
24
+ opacity: 1.0;
25
+
26
+ -webkit-transform: rotate(3deg) translate(0px, -4px);
27
+ -ms-transform: rotate(3deg) translate(0px, -4px);
28
+ transform: rotate(3deg) translate(0px, -4px);
29
+ }
30
+
31
+ #nprogress .spinner {
32
+ display: none;
33
+ position: fixed;
34
+ z-index: 1031;
35
+ top: 15px;
36
+ right: 15px;
37
+ }
38
+
39
+ @include media-breakpoint-down(sm) {
40
+ #nprogress .spinner {
41
+ bottom: 15px;
42
+ right: 15px;
43
+ top: initial;
44
+ }
45
+ }
46
+
47
+
48
+ #nprogress .spinner-icon {
49
+ width: 18px;
50
+ height: 18px;
51
+ box-sizing: border-box;
52
+
53
+ border: solid 2px transparent;
54
+ border-top-color: $nprogress-color;
55
+ border-left-color: $nprogress-color;
56
+ border-radius: 50%;
57
+
58
+ -webkit-animation: nprogress-spinner 400ms linear infinite;
59
+ animation: nprogress-spinner 400ms linear infinite;
60
+ }
61
+
62
+ .nprogress-custom-parent {
63
+ overflow: hidden;
64
+ position: relative;
65
+ }
66
+
67
+ .nprogress-custom-parent #nprogress .spinner,
68
+ .nprogress-custom-parent #nprogress .bar {
69
+ position: absolute;
70
+ }
71
+
72
+ @-webkit-keyframes nprogress-spinner {
73
+ 0% { -webkit-transform: rotate(0deg); }
74
+ 100% { -webkit-transform: rotate(360deg); }
75
+ }
76
+ @keyframes nprogress-spinner {
77
+ 0% { transform: rotate(0deg); }
78
+ 100% { transform: rotate(360deg); }
79
+ }
80
+
package/scss/sidebar.scss CHANGED
@@ -113,7 +113,32 @@
113
113
  font-size: 9px;
114
114
  line-height: 12px;
115
115
  }
116
- .search.bottom-sheet .dropdown-menu {
117
- max-height: 100%;
116
+
117
+ .navigation-dropdown, .user-dropdown {
118
+ > li {
119
+ > a, .dropdown-item {
120
+ padding: 10px 20px!important;
121
+ }
122
+ }
123
+ left: 0!important;
124
+ right: 0!important;
125
+ bottom: $spacer!important;
126
+ box-shadow: none!important;
127
+ max-height: 60vh!important;
128
+ overflow: auto!important;
129
+ }
130
+ .search-dropdown .quick-search-results {
131
+ max-height: 250px!important;
132
+ overflow-y: auto!important;
133
+ }
134
+ .search-dropdown, .chats-dropdown, .notifications-dropdown, .drafts-dropdown {
135
+ left: 0!important;
136
+ right: 0!important;
137
+ bottom: $spacer!important;
138
+ box-shadow: none!important;
139
+ ul {
140
+ max-height: 60vh!important;
141
+ overflow-y: auto!important;
142
+ }
118
143
  }
119
144
  }
@@ -1,5 +1,5 @@
1
1
  <div class="chats-full d-flex gap-1 vh-100 py-3">
2
- <div class="d-flex flex-column h-100" style="width:300px;" component="chat/nav-wrapper" data-loaded="{{{ if roomId }}}1{{{ else }}}0{{{ end }}}">
2
+ <div class="d-flex flex-column h-100" component="chat/nav-wrapper" data-loaded="{{{ if roomId }}}1{{{ else }}}0{{{ end }}}">
3
3
  <div class="chat-search dropdown mb-2">
4
4
  <label class="text-xs text-muted">[[users:search-user-for-chat]]</label>
5
5
 
@@ -6,8 +6,9 @@
6
6
 
7
7
  {{{ if roomId }}}
8
8
  <div component="chat/messages" class="expanded-chat d-flex flex-column h-100" data-roomid="{roomId}">
9
- <div component="chat/header" class="d-flex align-items-center px-3 gap-1">
10
- <h5 class="members flex-1 fw-semibold tracking-tight">
9
+ <div component="chat/header" class="d-flex align-items-center px-3 gap-2">
10
+ <a href="#" data-action="close" role="button" class="d-flex d-md-none btn btn-outline align-text-top"><i class="fa fa-chevron-left"></i></a>
11
+ <h5 class="members flex-1 fw-semibold tracking-tight mb-0">
11
12
  {./chatWithMessage}
12
13
  </h5>
13
14
 
@@ -14,7 +14,7 @@
14
14
  {{{ end }}}
15
15
  </div>
16
16
  <div class="message-body-wrapper hover-parent">
17
- <div component="chat/message/body" class="message-body ps-0 py-0 overflow-auto">
17
+ <div component="chat/message/body" class="message-body ps-0 py-0 overflow-auto text-break">
18
18
  {messages.content}
19
19
  </div>
20
20
 
@@ -1,13 +1,16 @@
1
1
  <div class="text-dark bg-light bottombar p-2 d-flex d-md-none justify-content-between fixed-bottom ff-secondary align-items-center">
2
- <div class="bottom-sheet">
3
- <button class="btn" data-bs-toggle="dropdown">
4
- <i class="fa fa-bars"></i>
5
- </button>
6
- <ul class="dropdown-menu">
2
+ <div class="">
3
+ <a href="#" role="button" class="nav-link nav-btn d-flex justify-content-between align-items-center position-relative" data-bs-toggle="dropdown">
4
+ <span class="position-relative">
5
+ <i class="fa fa-fw fa-lg fa-bars"></i>
6
+ <span component="unread/count" data-unread-url="{unreadCount.unreadUrl}" class="position-absolute top-0 start-100 translate-middle badge rounded-1 bg-primary {{{ if !unreadCount.mobileUnread }}}hidden{{{ end }}}">{unreadCount.mobileUnread}</span>
7
+ </span>
8
+ </a>
9
+ <ul class="navigation-dropdown dropdown-menu">
7
10
  {{{ each navigation }}}
8
11
  <!-- IF function.displayMenuItem, @index -->
9
12
  <li class="nav-item {./class}{{{ if ./dropdown }}} dropend{{{ end }}}" title="{./title}">
10
- <a class="nav-link nav-btn navigation-link p-3 {{{ if navigation.dropdown }}}dropdown-toggle{{{ end }}}"
13
+ <a class="nav-link nav-btn navigation-link px-3 py-2 {{{ if navigation.dropdown }}}dropdown-toggle{{{ end }}}"
11
14
  {{{ if ./dropdown }}} href="#" role="button" data-bs-toggle="collapse" data-bs-target="#collapse-target-{@index}" onclick="event.stopPropagation();" {{{ else }}} href="{./route}"{{{ end }}} {{{ if ./id }}}id="{./id}"{{{ end }}}{{{ if ./targetBlank }}} target="_blank"{{{ end }}}>
12
15
  <span class="d-inline-flex justify-content-between align-items-center w-100">
13
16
  <span class="text-nowrap truncate-open">
@@ -38,26 +41,26 @@
38
41
  {{{ if config.loggedIn }}}
39
42
  <ul id="logged-in-menu" class="list-unstyled d-flex align-items-center w-100 gap-3 mb-0">
40
43
  {{{ if config.searchEnabled }}}
41
- <li component="sidebar/search" class="nav-item m-0 search bottom-sheet position-relative">
44
+ <li component="sidebar/search" class="nav-item m-0 search">
42
45
  <!-- IMPORT partials/sidebar/search-mobile.tpl -->
43
46
  </li>
44
47
  {{{ end }}}
45
48
 
46
- <li component="notifications" class="nav-item m-0 notifications bottom-sheet">
49
+ <li component="notifications" class="nav-item m-0 notifications">
47
50
  <!-- IMPORT partials/sidebar/notifications.tpl -->
48
51
  </li>
49
52
 
50
53
  {{{ if canChat }}}
51
- <li class="nav-item m-0 chats bottom-sheet">
54
+ <li class="nav-item m-0 chats">
52
55
  <!-- IMPORT partials/sidebar/chats.tpl -->
53
56
  </li>
54
57
  {{{ end }}}
55
58
 
56
- <li component="sidebar/drafts" class="nav-item m-0 drafts bottom-sheet">
59
+ <li component="sidebar/drafts" class="nav-item m-0 drafts">
57
60
  <!-- IMPORT partials/sidebar/drafts.tpl -->
58
61
  </li>
59
62
 
60
- <li id="user_label" class="nav-item m-0 py-2 bottom-sheet usermenu">
63
+ <li id="user_label" class="nav-item m-0 py-2 usermenu">
61
64
  <!-- IMPORT partials/sidebar/user-menu.tpl -->
62
65
  </li>
63
66
  </ul>
@@ -16,10 +16,11 @@
16
16
  <a class="btn-ghost-sm d-none d-lg-flex align-self-stretch" target="_blank" href="{rssFeedUrl}" itemprop="item"><i class="fa fa-rss text-primary"></i></a>
17
17
  {{{ end }}}
18
18
 
19
- <span class="loading-indicator btn float-start text-muted navbar-text hidden" done="0">
20
- <i class="fa fa-refresh fa-spin"></i>
21
- <span class="hidden-xs">[[topic:loading_more_posts]]</span>
22
- </span>
19
+ {{{ if browsingUsers }}}
20
+ <div class="hidden-xs">
21
+ <!-- IMPORT partials/topic/browsing-users.tpl -->
22
+ </div>
23
+ {{{ end }}}
23
24
  </ul>
24
25
  <!-- IMPORT partials/topic/reply-button.tpl -->
25
26
  </div>
@@ -45,9 +45,12 @@
45
45
  </li>
46
46
  <li class="dropdown-divider"></li>
47
47
  <li class="notif-dropdown-link">
48
- <div class="d-flex justify-content-center gap-1 flex-nowrap">
49
- <a component="chats/mark-all-read" role="button" href="#" class="btn btn-sm btn-light mark-all-read flex-fill text-nowrap ff-secondary"><i class="fa fa-check-double"></i> [[modules:chat.mark_all_read]]</a>
50
- <a class="btn btn-sm btn-primary flex-fill text-nowrap ff-secondary" href="{relative_path}/user/{user.userslug}/chats"><i class="fa fa-list"></i> [[modules:chat.see_all]]</a>
48
+ <div class="d-flex justify-content-center gap-1 flex-wrap">
49
+ <a component="chats/mark-all-read" role="button" href="#" class="btn btn-sm btn-light mark-all-read flex-fill text-nowrap text-truncate ff-secondary"><i class="fa fa-check-double"></i> [[modules:chat.mark_all_read]]</a>
50
+ <!-- on md and up see all chats button goes to last room -->
51
+ <a class="d-none d-md-inline btn btn-sm btn-primary flex-fill text-nowrap text-truncate ff-secondary" href="{relative_path}/user/{user.userslug}/chats{{{ if user.lastRoomId }}}/{user.lastRoomId}{{{ end }}}"><i class="fa fa-list"></i> [[modules:chat.see_all]]</a>
52
+ <!-- on xs&sm the see all chats button goes to the list of chats -->
53
+ <a class="d-inline d-md-none btn btn-sm btn-primary flex-fill text-nowrap text-truncate ff-secondary" href="{relative_path}/user/{user.userslug}/chats"><i class="fa fa-list"></i> [[modules:chat.see_all]]</a>
51
54
  </div>
52
55
  </li>
53
56
  </ul>
@@ -22,12 +22,12 @@
22
22
  <div class="dropdown-item rounded-1 p-2 d-flex flex-column gap-2 pointer" component="drafts/open" data-save-id="{./save_id}">
23
23
  {{{ if (./action == "topics.post") }}}
24
24
  {{{ if ./title}}}
25
- <div class="text text-xs fw-semibold line-clamp-2">{./title}</div>
25
+ <div class="text text-xs fw-semibold line-clamp-2 text-break">{./title}</div>
26
26
  {{{ end }}}
27
27
  {{{ end }}}
28
28
 
29
29
  {{{ if (./action == "posts.reply") }}}
30
- <div class="text text-xs fw-semibold line-clamp-2">[[topic:composer.replying_to, "{./title}"]]</div>
30
+ <div class="text text-xs fw-semibold line-clamp-2 text-break">[[topic:composer.replying_to, "{./title}"]]</div>
31
31
  {{{ end }}}
32
32
 
33
33
  {{{ if (./action == "posts.edit") }}}
@@ -8,7 +8,7 @@
8
8
  </span>
9
9
  <span component="notifications/count" class="visible-open badge rounded-1 bg-primary {{{ if !unreadCount.notification }}}hidden{{{ end }}}">{unreadCount.notification}</span>
10
10
  </a>
11
- <ul class="notifications-dropdown dropdown-menu p-2 shadow">
11
+ <ul class="notifications-dropdown dropdown-menu p-1 shadow">
12
12
  <li>
13
13
  <ul component="notifications/list" class="notification-list list-unstyled">
14
14
  <li class="mb-2 placeholder-wave">
@@ -20,9 +20,9 @@
20
20
  </li>
21
21
  <li class="dropdown-divider"></li>
22
22
  <li class="notif-dropdown-link">
23
- <div class="d-flex justify-content-center gap-1 flex-nowrap">
24
- <a role="button" href="#" class="btn btn-sm btn-light mark-all-read flex-fill text-nowrap ff-secondary"><i class="fa fa-check-double"></i> [[notifications:mark_all_read]]</a>
25
- <a class="btn btn-sm btn-primary flex-fill text-nowrap ff-secondary" href="{relative_path}/notifications"><i class="fa fa-list"></i> [[notifications:see_all]]</a>
23
+ <div class="d-flex justify-content-center gap-1 flex-wrap">
24
+ <a role="button" href="#" class="btn btn-sm btn-light mark-all-read flex-fill text-nowrap text-truncate ff-secondary"><i class="fa fa-check-double"></i> [[notifications:mark_all_read]]</a>
25
+ <a class="btn btn-sm btn-primary flex-fill text-nowrap text-truncate ff-secondary" href="{relative_path}/notifications"><i class="fa fa-list"></i> [[notifications:see_all]]</a>
26
26
  </div>
27
27
  </li>
28
28
  </ul>
@@ -15,7 +15,7 @@
15
15
  <div class="quick-search-results-container"></div>
16
16
  </div>
17
17
 
18
- <div class="d-flex gap-1 input-container mt-2">
18
+ <div class="d-flex gap-1 input-container">
19
19
  <input autocomplete="off" type="text" class="form-control" placeholder="[[global:search]]" name="query" value="">
20
20
 
21
21
  <div class="nav-btn d-flex justify-content-center align-items-center advanced-search-link">
@@ -2,7 +2,7 @@
2
2
  {buildAvatar(user, "20px", true)}
3
3
  <span id="user-header-name" class="nav-text small visible-open fw-semibold">{user.username}</span>
4
4
  </label>
5
- <ul id="user-control-list" component="header/usercontrol" class="dropdown-menu shadow p-1 text-sm" aria-labelledby="user_dropdown">
5
+ <ul id="user-control-list" component="header/usercontrol" class="user-dropdown dropdown-menu shadow p-1 text-sm" aria-labelledby="user_dropdown">
6
6
  <li>
7
7
  <a class="dropdown-item rounded-1 d-flex align-items-center gap-1" component="header/profilelink" href="{relative_path}/user/{user.userslug}">
8
8
  <div class="text-center"><span component="user/status" class="badge border border-white border-2 rounded-circle status {user.status}"><span class="visually-hidden">[[global:{user.status}]]</span></span></div>
@@ -28,7 +28,10 @@
28
28
  {{{end}}}
29
29
  </ul>
30
30
  <div class="w-100">
31
+ {{{ if !config.disableCustomUserSkins }}}
31
32
  <!-- IMPORT partials/skin-switcher.tpl -->
33
+ {{{ end }}}
34
+
32
35
  <div class="sidebar-toggle m-2 d-none d-lg-block">
33
36
  <a href="#" role="button" component="sidebar/toggle" class="nav-btn d-flex gap-2 align-items-center p-2 pointer nav-link w-100 text-nowrap">
34
37
  <i class="fa fa-fw fa-angles-right"></i>
@@ -9,12 +9,12 @@
9
9
  <form class="flex-grow-1 d-flex flex-column gap-2" method="post" action="{config.relative_path}/compose">
10
10
  <input type="hidden" name="tid" value="{tid}" />
11
11
  <input type="hidden" name="_csrf" value="{config.csrf_token}" />
12
- <div class="quickreply-message">
12
+ <div class="quickreply-message position-relative">
13
13
  <textarea rows="4" name="content" component="topic/quickreply/text" class="form-control mousetrap" placeholder="[[modules:composer.textarea.placeholder]]"></textarea>
14
14
  <div class="imagedrop"><div>[[topic:composer.drag_and_drop_images]]</div></div>
15
15
  </div>
16
16
  <div>
17
- <div class="btn-group">
17
+ <div class="d-flex justify-content-end gap-2">
18
18
  <button type="submit" component="topic/quickreply/button" class="btn btn-sm btn-primary">[[topic:post-quick-reply]]</button>
19
19
  <button type="submit" component="topic/quickreply/expand" class="btn btn-sm btn-primary" formmethod="get"><i class="fa fa-expand"></i></button>
20
20
  </div>
@@ -14,7 +14,7 @@
14
14
  <div class="avatar">
15
15
  <a href="{{{ if ./user.userslug }}}{config.relative_path}/user/{./user.userslug}{{{ else }}}#{{{ end }}}" class="text-decoration-none">
16
16
  {{{ if ./thumbs.length }}}
17
- <img src="{./thumbs.0.url}" class="not-responsive" />
17
+ <img class="topic-thumb rounded-1" width="80" height="auto" src="{./thumbs.0.url}" class="not-responsive" />
18
18
  {{{ else }}}
19
19
  {buildAvatar(./user, "40px", true, "not-responsive")}
20
20
  {{{ end }}}
@@ -22,7 +22,7 @@
22
22
  </div>
23
23
  </div>
24
24
  <div class="d-flex flex-column gap-1">
25
- <h2 component="topic/header" class="title mb-1 {{{ if showSelect }}}me-4{{{ end }}} me-md-0 text-md fw-bold">
25
+ <h2 component="topic/header" class="text-break title mb-1 {{{ if showSelect }}}me-4{{{ end }}} me-md-0 text-md fw-bold">
26
26
  {{{ if topics.noAnchor }}}
27
27
  <span>{./title}</span>
28
28
  {{{ else }}}
@@ -6,12 +6,12 @@
6
6
  </div>
7
7
  {{{ end }}}
8
8
 
9
- <h2 component="post/header" class="fs-2 mb-0 {{{ if config.centerHeaderElements }}}text-center{{{ end }}}" itemprop="name">
9
+ <h2 component="post/header" class="fs-2 mb-0 text-break {{{ if config.centerHeaderElements }}}text-center{{{ end }}}" itemprop="name">
10
10
  <span class="topic-title" component="topic/title">{title}</span>
11
11
  </h2>
12
12
 
13
13
  <div class="topic-info d-flex gap-2 align-items-center flex-wrap {{{ if config.centerHeaderElements }}}justify-content-center{{{ end }}}">
14
- <span component="topic/labels" class="d-flex gap-2">
14
+ <span component="topic/labels" class="d-flex gap-2 lh-1">
15
15
  <span component="topic/scheduled" class="badge badge border border-gray-300 text-primary {{{ if !scheduled }}}hidden{{{ end }}}">
16
16
  <i class="fa fa-clock-o"></i>
17
17
  [[topic:scheduled]]
@@ -28,7 +28,7 @@
28
28
  <i class="fa fa-arrow-circle-right"></i>
29
29
  {{{ if privileges.isAdminOrMod }}}[[topic:moved-from, {oldCategory.name}]]{{{ else }}}[[topic:moved]]{{{ end }}}
30
30
  </span>
31
- {{{each icons}}}<span class="align-middle">{@value}</span>{{{end}}}
31
+ {{{each icons}}}<span>{@value}</span>{{{end}}}
32
32
  </span>
33
33
  <a class="lh-1" href="{config.relative_path}/category/{category.slug}">{function.buildCategoryLabel, category, "border"}</a>
34
34
  <div class="lh-1 tags tag-list d-flex hidden-xs gap-2"><!-- IMPORT partials/topic/tags.tpl --></div>