diff --git a/_config.yml b/_config.yml
index a439d14..1629d35 100755
--- a/_config.yml
+++ b/_config.yml
@@ -124,7 +124,8 @@ plugins:
css: https://unpkg.com/swiper/swiper-bundle.min.css
js: https://unpkg.com/swiper/swiper-bundle.min.js
# issues api
- issuesjs: /js/issues.js
+ sitesjs: /js/plugins/sites.js
+ friendsjs: /js/plugins/friends.js
## optional plugins ##
# preload
diff --git a/layout/_partial/scripts/index.ejs b/layout/_partial/scripts/index.ejs
index 5c82982..b14d8b7 100644
--- a/layout/_partial/scripts/index.ejs
+++ b/layout/_partial/scripts/index.ejs
@@ -13,7 +13,8 @@
// required plugins (only load if needs)
stellar.plugins = {
jQuery: '<%- url_for(theme.plugins.jquery || "https://cdn.jsdelivr.net/npm/jquery@latest/dist/jquery.min.js") %>',
- issuesjs: '<%- url_for(theme.plugins.issuesjs || "/js/issues.js") %>',
+ sitesjs: '<%- url_for(theme.plugins.sitesjs) %>',
+ friendsjs: '<%- url_for(theme.plugins.friendsjs) %>',
};
// optional plugins
diff --git a/scripts/tags/friends.js b/scripts/tags/friends.js
index db0e1aa..86f4ebc 100644
--- a/scripts/tags/friends.js
+++ b/scripts/tags/friends.js
@@ -2,61 +2,56 @@
* friends.js v1 | https://github.com/xaoxuu/hexo-theme-stellar/
* 格式与官方标签插件一致使用空格分隔,中括号内的是可选参数(中括号不需要写出来)
*
- * {% friends [style:rect] [group:name] %}
- * {% friends [api:https://issues-api.vercel.app] [repo:xaoxuu/friends] %}
+ * {% friends [group:name] %}
*/
'use strict';
hexo.extend.tag.register('friends', function(args) {
- args = hexo.args.map(args, ['style', 'group', 'repo']);
+ args = hexo.args.map(args, ['group']);
var friends = hexo.locals.get('data').friends;
if (friends == undefined) {
friends = {};
}
- var el = '
';
- if (args.repo) {
- el += '
';
- } else {
- function groupHeader(group) {
- var header = '';
- return header;
+ var el = '
';
+ function groupHeader(group) {
+ var header = '';
+ return header;
+ }
+ function cell(friend) {
+ if (friend.url && friend.title) {
+ var cell = '
'
+ return cell;
+ } else {
+ return '';
+ }
+ }
+ for (let groupId of Object.keys(friends)) {
+ function f() {
+ if (groupId in friends) {
+ let group = friends[groupId];
+ if (group.title || group.description) {
el += groupHeader(group);
+ }
+ if (group.repo) {
+ el += '
';
+ } else if (group.items) {
el += '
';
group.items.forEach((friend, i) => {
el += cell(friend);
@@ -64,13 +59,13 @@ hexo.extend.tag.register('friends', function(args) {
el += '
';
}
}
- if (args.group && args.group.length > 0) {
- if (args.group == groupId) {
- f();
- }
- } else {
+ }
+ if (args.group && args.group.length > 0) {
+ if (args.group == groupId) {
f();
}
+ } else {
+ f();
}
}
el += '
';
diff --git a/scripts/tags/site.js b/scripts/tags/site.js
new file mode 100644
index 0000000..4da120c
--- /dev/null
+++ b/scripts/tags/site.js
@@ -0,0 +1,77 @@
+/**
+ * sites.js v1 | https://github.com/xaoxuu/hexo-theme-stellar/
+ * 格式与官方标签插件一致使用空格分隔,中括号内的是可选参数(中括号不需要写出来)
+ *
+ * {% site [group:name] %}
+ */
+
+'use strict';
+
+hexo.extend.tag.register('sites', function(args) {
+ args = hexo.args.map(args, ['group']);
+ var sites = hexo.locals.get('data').sites;
+ if (sites == undefined) {
+ sites = {};
+ }
+ var el = '
';
+ function groupHeader(group) {
+ var header = '';
+ return header;
+ }
+ function cell(site) {
+ if (site.url && site.title) {
+ var cell = '
'
+ return cell;
+ } else {
+ return '';
+ }
+ }
+ for (let groupId of Object.keys(sites)) {
+ function f() {
+ if (groupId in sites) {
+ let group = sites[groupId];
+ if (group.title || group.description) {
+ el += groupHeader(group);
+ }
+ if (group.repo) {
+ el += '
';
+ } else if (group.items) {
+ el += '
';
+ group.items.forEach((site, i) => {
+ el += cell(site);
+ });
+ el += '
';
+ }
+ }
+ }
+ if (args.group && args.group.length > 0) {
+ if (args.group == groupId) {
+ f();
+ }
+ } else {
+ f();
+ }
+ }
+ el += '
';
+ return el;
+});
diff --git a/source/css/_layout/pages/friends.styl b/source/css/_layout/pages/friends.styl
deleted file mode 100644
index e053c6e..0000000
--- a/source/css/_layout/pages/friends.styl
+++ /dev/null
@@ -1,73 +0,0 @@
-.friends-wrap
- .group-header
- margin: 1rem 0
- p
- margin: 0
- p.title
- font-size: 1.125rem
- font-weight: 500
- p.description
- font-size: $fs14
- .group-body
- display: grid
- grid-gap: 4px 4px
- grid-template-columns: repeat(auto-fill, 96px)
- margin-bottom: 2rem
-
-.friends-wrap .user-simple
- a
- margin: auto
- color: var(--text-p1)
- font-size: $fs12
- display: flex
- flex-direction: column
- align-items: center
- text-align: center
- line-height: 1.2
- border-radius: 4px
- overflow: hidden
- position: relative
- background: var(--card)
- img
- object-fit: cover
- display: block
- width: 64px
- height: 64px
- .name
- padding-top: 0.5em
-
-
-
-// style
-.friends-wrap.round .user-simple
- a
- padding: 0.5rem
- trans1: background
- img
- border-radius: 64px
- margin-top: 0.5rem
- margin-bottom: 2rem
- .name
- position: absolute
- height: 2rem
- bottom: 0
- &:hover
- background: var(--hover-block)
-
-.friends-wrap.rect .user-simple
- a
- padding: 0
- display: block
- trans1: box-shadow
- img
- width: 96px
- height: 96px
- border-radius: 0
- .name
- padding: 0 0.5em
- height: 2rem
- display: flex
- justify-content: center
- align-items: center
- &:hover
- box-shadow: $boxshadow-card-float
diff --git a/source/css/_layout/tag-plugins/friends.styl b/source/css/_layout/tag-plugins/friends.styl
new file mode 100644
index 0000000..8853fde
--- /dev/null
+++ b/source/css/_layout/tag-plugins/friends.styl
@@ -0,0 +1,68 @@
+.friends-wrap
+ overflow: hidden
+ .group-header
+ margin: 0 0 1rem
+ p
+ margin: 0
+ font-size: $fs14
+ &:first-child
+ font-size: 1.25rem
+ font-weight: 500
+ .group-body
+ width: 100%
+ display: flex
+ flex-wrap: wrap
+ align-items: stretch
+ margin-bottom: 2rem
+ .friendsjs-wrap
+ display: block
+ .loading-wrap
+ min-height: 50px
+ margin: 2rem 0
+ text-align: center
+
+.friends-wrap .user-simple
+ flex-shrink: 1
+ display: flex
+ align-items: stretch
+ width: 12.5%
+ @media screen and (max-width: 980px)
+ width: 14.28%
+ @media screen and (max-width: 900px)
+ width: 16.66%
+ @media screen and (max-width: 820px)
+ width: 20%
+ @media screen and (max-width: $device-tablet)
+ width: 16.66%
+ @media screen and (max-width: $device-mobile)
+ width: 25%
+ a
+ margin: 0
+ width: 100%
+ color: var(--text-p1)
+ font-size: 10px
+ font-weight: 500
+ display: flex
+ justify-content: flex-start
+ flex-direction: column
+ align-items: center
+ text-align: center
+ line-height: 1.2
+ border-radius: 4px
+ overflow: hidden
+ position: relative
+ padding: 1rem 0.5rem
+ img
+ object-fit: cover
+ display: block
+ width: 48px
+ height: 48px
+ background: var(--card)
+ border-radius: 64px
+ margin: 0 0 0.5rem
+ trans2 transform box-shadow
+ &:hover
+ background: var(--hover-block)
+ img
+ transform: scale(1.2) rotate(8deg)
+ box-shadow: $boxshadow-card-float
diff --git a/source/css/_layout/tag-plugins/site-card.styl b/source/css/_layout/tag-plugins/site-card.styl
deleted file mode 100644
index 04f97bb..0000000
--- a/source/css/_layout/tag-plugins/site-card.styl
+++ /dev/null
@@ -1,68 +0,0 @@
-.site-card-group
- display: grid
- grid-gap: $gap $gap
- grid-template-columns: repeat(auto-fill, "calc((100% - 3 * %s) / 4)" % $gap)
- @media screen and (max-width: $device-laptop)
- grid-template-columns: repeat(auto-fill, "calc((100% - 2 * %s) / 3)" % $gap)
- @media screen and (max-width: $device-mobile)
- grid-template-columns: repeat(auto-fill, "calc((100% - 1 * %s) / 2)" % $gap)
- margin-bottom: 2rem
-
-.site-card-group .site-card
- line-height: 1.2
- disable-select()
- color: var(--text-p1)
- .img
- width: 100%
- height 100px
- @media screen and (max-width: $device-mobile)
- height 80px
- overflow: hidden
- border-radius: $border-card * 0.5
- box-shadow: 0 1px 2px 0px rgba(0, 0, 0, 0.2)
- background: var(--color-block)
- img
- width: 100%
- height 100%
- transition: transform 2s ease
- object-fit: cover
-
- .info
- margin-top: $gap * 0.5
- img
- width: 32px
- height: 32px
- border-radius: 16px
- float: left
- margin-right: 8px
- margin-top: 2px
- span
- display: block
- .title
- font-weight: 600
- color: var(--text-p1)
- font-size: $fs15
- margin-top: 1px
- color: var(--color-p)
- display: -webkit-box
- -webkit-box-orient: vertical
- overflow: hidden
- -webkit-line-clamp: 1
-
- .desc
- font-size: $fs12
- color: var(--text-p2)
- margin-top: 2px
- word-wrap: break-word;
- color: var(--color-meta)
- display: -webkit-box
- -webkit-box-orient: vertical
- overflow: hidden
- -webkit-line-clamp: 2
- .img
- trans1 box-shadow
- &:hover
- .img
- box-shadow: $boxshadow-float, $boxshadow-card-float
- .info .title
- color: $color-hover
diff --git a/source/css/_layout/tag-plugins/sites.styl b/source/css/_layout/tag-plugins/sites.styl
new file mode 100644
index 0000000..fbcaece
--- /dev/null
+++ b/source/css/_layout/tag-plugins/sites.styl
@@ -0,0 +1,83 @@
+.sites-wrap
+ .group-header
+ margin: 0 0 1rem
+ p
+ margin: 0
+ font-size: $fs14
+ &:first-child
+ font-size: 1.25rem
+ font-weight: 500
+ .group-body
+ width: 100%
+ margin-bottom: 2rem
+ .sitesjs-wrap
+ display: block
+ .loading-wrap
+ min-height: 50px
+ margin: 2rem 0
+ text-align: center
+
+.sites-wrap .group-body
+ display: grid
+ grid-gap: $gap $gap
+ grid-template-columns: repeat(auto-fill, "calc((100% - 3 * %s) / 4)" % $gap)
+ @media screen and (max-width: $device-laptop)
+ grid-template-columns: repeat(auto-fill, "calc((100% - 2 * %s) / 3)" % $gap)
+ @media screen and (max-width: 900px)
+ grid-template-columns: repeat(auto-fill, "calc((100% - 1 * %s) / 2)" % $gap)
+ @media screen and (max-width: $device-tablet)
+ grid-template-columns: repeat(auto-fill, "calc((100% - 2 * %s) / 3)" % $gap)
+ @media screen and (max-width: $device-mobile)
+ grid-template-columns: repeat(auto-fill, "calc((100% - 1 * %s) / 2)" % $gap)
+ margin-bottom: 2rem
+
+.sites-wrap .group-body .site-card .site-link
+ width: 100%
+ display: flex
+ flex-direction: column
+ >img
+ width: 100%
+ height 100px
+ @media screen and (max-width: $device-laptop)
+ height: 120px
+ @media screen and (max-width: 900px)
+ height: 150px
+ @media screen and (max-width: $device-tablet)
+ height: 120px
+ object-fit: cover
+ box-shadow: 0 1px 2px 0px rgba(0, 0, 0, 0.2)
+ trans1: box-shadow
+ .info
+ margin-top: $gap * 0.5
+ line-height: 1.2
+ >img
+ width: 28px
+ height: @width
+ border-radius: @width
+ float: left
+ margin-right: 8px
+ margin-top: 2px
+ span
+ display: block
+ .title
+ font-weight: 500
+ color: var(--text-p1)
+ font-size: $fs14
+ margin-top: 1px
+ display: -webkit-box
+ -webkit-box-orient: vertical
+ overflow: hidden
+ -webkit-line-clamp: 1
+ .desc
+ font-size: 10px
+ margin-top: 2px
+ word-wrap: break-word
+ color: var(--text-p3)
+ display: -webkit-box
+ -webkit-box-orient: vertical
+ overflow: hidden
+ -webkit-line-clamp: 2
+
+.sites-wrap .group-body .site-card .site-link:hover
+ >img
+ box-shadow: $boxshadow-float, $boxshadow-card-float
diff --git a/source/js/main.js b/source/js/main.js
index 37db151..8c57daa 100644
--- a/source/js/main.js
+++ b/source/js/main.js
@@ -278,11 +278,20 @@ if (stellar.plugins.lazyload) {
}
// issuesjs
-if (stellar.plugins.issuesjs) {
- const issues_api = document.getElementById('issues-api');
+if (stellar.plugins.sitesjs) {
+ const issues_api = document.getElementById('sites-api');
if (issues_api != undefined) {
util.jQuery( () => {
- util.loadScript(stellar.plugins.issuesjs, {defer:true})
+ util.loadScript(stellar.plugins.sitesjs, {defer:true})
+ })
+ }
+}
+if (stellar.plugins.friendsjs) {
+ const issues_api = document.getElementById('friends-api');
+ if (issues_api != undefined) {
+ console.log(issues_api);
+ util.jQuery( () => {
+ util.loadScript(stellar.plugins.friendsjs, {defer:true})
})
}
}
diff --git a/source/js/issues.js b/source/js/plugins/friends.js
similarity index 55%
rename from source/js/issues.js
rename to source/js/plugins/friends.js
index 697ae1f..dedc657 100644
--- a/source/js/issues.js
+++ b/source/js/plugins/friends.js
@@ -1,5 +1,5 @@
-const IssuesAPI = {
- requestIssuesAPI(url, callback, timeout) {
+const friendsjs = {
+ requestAPI: (url, callback, timeout) => {
let retryTimes = 5;
function request() {
return new Promise((resolve, reject) => {
@@ -42,45 +42,43 @@ const IssuesAPI = {
}
request();
},
- getIssuesAPIForFriends(cfg) {
+ layout: (cfg) => {
const el = $(cfg.el)[0];
- $(el).append('
');
- this.requestIssuesAPI(cfg.api, function(data) {
- $(el).find('.loading').remove();
+ $(el).append('
');
+ friendsjs.requestAPI(cfg.api, function(data) {
+ $(el).find('.loading-wrap').remove();
const arr = data.content;
arr.forEach((item, i) => {
var user = '
';
$(el).find('.group-body').append(user);
});
}, function() {
- $(el).find('.loading i').remove();
- $(el).find('.loading p').text('加载失败,请稍后重试。');
+ $(el).find('.loading-wrap svg').remove();
+ $(el).find('.loading-wrap p').text('加载失败,请稍后重试。');
});
},
- request() {
- const els = document.getElementsByClassName('issues-wrap');
- for (var i = 0; i < els.length; i++) {
- const el = els[i];
- const api = el.getAttribute('api');
- const group = el.getAttribute('group');
- if (api == null) {
- continue;
- }
- var cfg = new Object();
- cfg.class = el.getAttribute('class');
- cfg.el = el;
- cfg.api = api;
- cfg.group = group;
- this.getIssuesAPIForFriends(cfg);
- }
- }
-};
+}
+
$(function () {
- IssuesAPI.request();
+ const els = document.getElementsByClassName('friendsjs-wrap');
+ for (var i = 0; i < els.length; i++) {
+ const el = els[i];
+ const api = el.getAttribute('api');
+ const group = el.getAttribute('group');
+ if (api == null) {
+ continue;
+ }
+ var cfg = new Object();
+ cfg.class = el.getAttribute('class');
+ cfg.el = el;
+ cfg.api = api;
+ cfg.group = group;
+ friendsjs.layout(cfg);
+ }
});
diff --git a/source/js/plugins/sites.js b/source/js/plugins/sites.js
new file mode 100644
index 0000000..969c16c
--- /dev/null
+++ b/source/js/plugins/sites.js
@@ -0,0 +1,87 @@
+const sitesjs = {
+ requestAPI: (url, callback, timeout) => {
+ let retryTimes = 5;
+ function request() {
+ return new Promise((resolve, reject) => {
+ let status = 0; // 0 等待 1 完成 2 超时
+ let timer = setTimeout(() => {
+ if (status === 0) {
+ status = 2;
+ timer = null;
+ reject('请求超时');
+ if (retryTimes == 0) {
+ timeout();
+ }
+ }
+ }, 5000);
+ fetch(url).then(function(response) {
+ if (status !== 2) {
+ clearTimeout(timer);
+ resolve(response);
+ timer = null;
+ status = 1;
+ }
+ if (response.ok) {
+ return response.json();
+ }
+ throw new Error('Network response was not ok.');
+ }).then(function(data) {
+ retryTimes = 0;
+ callback(data);
+ }).catch(function(error) {
+ if (retryTimes > 0) {
+ retryTimes -= 1;
+ setTimeout(() => {
+ request();
+ }, 5000);
+ } else {
+ timeout();
+ }
+ });
+ });
+ }
+ request();
+ },
+ layout: (cfg) => {
+ const el = $(cfg.el)[0];
+ $(el).append('
');
+ sitesjs.requestAPI(cfg.api, function(data) {
+ $(el).find('.loading-wrap').remove();
+ const arr = data.content;
+ arr.forEach((item, i) => {
+ var cell = '
';
+ $(el).find('.group-body').append(cell);
+ });
+ }, function() {
+ $(el).find('.loading-wrap svg').remove();
+ $(el).find('.loading-wrap p').text('加载失败,请稍后重试。');
+ });
+ },
+}
+
+$(function () {
+ const els = document.getElementsByClassName('sitesjs-wrap');
+ for (var i = 0; i < els.length; i++) {
+ const el = els[i];
+ const api = el.getAttribute('api');
+ const group = el.getAttribute('group');
+ if (api == null) {
+ continue;
+ }
+ var cfg = new Object();
+ cfg.class = el.getAttribute('class');
+ cfg.el = el;
+ cfg.api = api;
+ cfg.group = group;
+ sitesjs.layout(cfg);
+ }
+});