icarus个性化配置 饼干 2021-11-26 2021-11-27
本博客所选取的主题是 Icarus ,并做了一些个性化的修改,很多修改都可以直观的看到。
布局 文章页面两栏布局主题默认是双栏布局,在阅读文章时显得有些拥挤。可以通过配置的方式把所有文章变为两栏布局,在_config.post.yml
把需要的widget
显示在一边即可,可以参考官方文档 。
但两栏整体宽度跟三栏不同,因此强制指定为三栏布局,并且修改相应的宽度,这样所有的页面侧边栏宽度保持一致。
layout/layout.jsx 1 2 3 4 <Head site={site} config={config} helper={helper} page={page} /> - <body class={`is-${columnCount}-column`}> + <body class={`is-3-column`}> <Navbar config={config} helper={helper} page={page} />
layout/layout.jsx 1 2 3 4 'is-12': columnCount === 1, - 'is-8-tablet is-8-desktop is-8-widescreen': columnCount === 2, + 'is-8-tablet is-8-desktop is-9-widescreen': columnCount === 2, 'is-8-tablet is-8-desktop is-6-widescreen': columnCount === 3
layout/common/widgets.jsx 1 2 3 4 5 6 7 8 function getColumnSizeClass(columnCount) { switch (columnCount) { case 2: - return 'is-4-tablet is-4-desktop is-4-widescreen'; + return 'is-4-tablet is-4-desktop is-3-widescreen'; case 3: return 'is-4-tablet is-4-desktop is-3-widescreen'; }
并优化在不同屏幕小大下的宽度
include/style/responsive.styl 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 +widescreen() + .is-3-column .container + max-width: $widescreen - $gap + width: $widescreen - $gap + .is-1-column .container, .is-2-column .container max-width: $desktop - 2 * $gap width: $desktop - 2 * $gap +fullhd() + .is-3-column .container + max-width: $fullhd - 2 * $gap + width: $fullhd - 2 * $gap + .is-2-column .container max-width: $widescreen - 2 * $gap width: $widescreen - 2 * $gap
优化文章标题布局 标题移动到文章信息上方,增加更新时间,并增加了icon
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 diff: layout/common/article.jsx <article class={`card-content article${'direction' in page ? ' ' + page.direction : ''}`} role="article"> {/* Metadata */} + {/* Title */} + <h1 className="title is-size-3 is-size-4-mobile has-text-weight-normal"> + {index ? + <a className="has-link-black-ter" href={url_for(page.link || page.path)}> + <i className="fas fa-angle-double-right"></i>{page.title} + </a> : + [<i className="fas fa-angle-double-right"></i>, page.title] + } + </h1> {page.layout !== 'page' ? <div class="article-meta is-size-7 is-uppercase level is-mobile"> <div class="level-left"> {/* Creation Date */} - {page.date && <span class="level-item" dangerouslySetInnerHTML={{ - __html: _p('article.created_at', `<time dateTime="${date_xml(page.date)}" title="${new Date(page.date).toLocaleString()}">${date( page.date)}</time>`) - }}></span>} + {page.date && <span class="level-item"> + <i className="far fa-calendar-alt"> </i> + <time dateTime={date_xml(page.date)} title={date_xml(page.date)}>{date(page.date)}</time> + </span>} {/* Last Update Date */} - {page.updated && <span class="level-item" dangerouslySetInnerHTML={{ - __html: _p('article.updated_at', `<time dateTime="${date_xml(page.updated)}" title="${new Date(page.updated).toLocaleString()}">$ {date(page.updated)}</time>`) - }}></span>} + {shouldShowUpdated && <span class="level-item is-hidden-mobile"> + <i class="far fa-calendar-check"> </i> + <time dateTime={date_xml(page.updated)} title={date_xml(page.updated)}>{date(page.updated)}</time> + </span>} {/* author */} {page.author ? <span class="level-item"> {page.author} </span> : null}
其中时间直接使用日期
source/js/main.js 1 2 3 4 5 - if (typeof moment === 'function') { - $('.article-meta time').each(function() { - $(this).text(moment($(this).attr('datetime')).fromNow()); - }); - }
优化文章结尾布局 在文章结尾增加一个 hr,并修改 tags 展示。在预览时(主页)也显示 tags,并且将 Read More 按钮放置在右边。
layout/common/article.jsx 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 {/* Licensing block */} {!index && article && article.licenses && Object.keys(article.licenses) ? <ArticleLicensing.Cacheable page={page} config={config} helper={helper} /> : null} + <hr style="height:1px;margin:1rem 0"/> + <div className="level is-mobile is-flex"> {/* Tags */} - {!index && page.tags && page.tags.length ? <div class="article-tags is-size-7 mb-4"> - <span class="mr-2">#</span> - {page.tags.map(tag => { - return <a class="link-muted mr-2" rel="tag" href={url_for(tag.path)}>{tag.name}</a>; + {page.tags && page.tags.length ? <div class="article-tags is-size-7 is-uppercase"> + <i class="fas fa-tags has-text-grey"></i> + {page.tags.map((tag, index) => { + return <a class="link-muted" rel="tag" href={url_for(tag.path)}>{tag.name}{index !== page.tags.length-1? ', ':''}</a>; })} </div> : null} {/* "Read more" button */} - {index && page.excerpt ? <a class="article-more button is-small is-size-7" href={`${url_for(page.link || page.path)}#more`}>{__('article.more')}</a> : null} + {index && page.excerpt ? <a class="article-more button is-small is-size-7" href={`${url_for(page.link || page.path)}#more`}><i class="fas fa-book-reader has-text-grey"></i> {__('article.more')}</a> : null} + </div> {/* Share button */}
优化个人信息布局 减少头像大小,头像下方计数的地方增加链接,follow前增加icon。
1 2 3 4 5 6 7 8 9 10 11 12 13 diff: layout/widget/profile.jsx - <div class="level-item has-text-centered is-marginless"> + <a class="level-item has-text-centered is-marginless" href={counter.category.url}> <div> <p class="heading">{counter.category.title}</p> - <a href={counter.category.url}> + <div> <p class="title">{counter.category.count}</p> - </a> + </div> </div> - </div> + </a>
优化移动端显示 在移动端,隐藏 archive 和 tags。
source/js/main.js 1 2 3 4 5 } + + $('div.container div.card[data-type=tags]').addClass('is-hidden-mobile'); + $('div.container div.card[data-type=archives]').addClass('is-hidden-mobile'); }(jQuery, window.moment, window.ClipboardJS, window.IcarusThemeSettings));
目录粘性定位 原来只支持侧边栏整体粘性定位,为了阅读体验,只针对目录开启粘性定位,增加 column-left is-sticky 类,并调整样式
source/js/main.js 1 2 3 if ($toc.length > 0) { + $toc.addClass('column-left is-sticky'); const $mask = $('<div>');
include/style/widget.styl 1 2 3 +#toc + max-height: calc(100vh - 22px) + overflow-y: scroll
功能 增加默认缩略图 1 2 3 4 5 6 diff: layout/layout.jsx const { site, config, page, helper, body } = this.props; + site.posts && site.posts.filter(p => !p.thumbnail).forEach(p => p.thumbnail = '/img/thumbnail.svg'); + const language = page.lang || page.language || config.language;
layout/archive.jsx 1 2 3 4 5 const { url_for, __, date_xml, date } = helper; + page.posts && page.posts.filter(p => !p.thumbnail).forEach(p => p.thumbnail = '/img/thumbnail.svg'); + const language = page.lang || page.language || config.language;
增加许可协议 新版已经支持许可协议,直接配置即可,参考官方文档 。
增加标题自动计数 1 2 3 4 5 6 7 8 diff: include/style/article.styl +.article {counter-reset:section} +.article h2{counter-reset:sub-section} +.article h3{counter-reset:composite} +.article h4{counter-reset:detail} +.article h2:before{content:counter(section) " ";counter-increment:section} +.article h3:before{content:counter(section) "." counter(sub-section) " ";counter-increment:sub-section} +.article h4:before{content:counter(section) "." counter(sub-section) "." counter(composite) " ";counter-increment:composite}
默认显示目录 新版支持直接配置,在_config.yml增加toc: true即可。
默认情况下一个icon对应一个链接,但例如 CC BY-NC-SA 4.0 需要四个图标一组。因此修改代码,使得配置 link.icon 可以是一个数组,效果可以参考页面底部。
layout/common/footer.jsx 1 2 3 4 5 6 7 8 9 10 11 12 const link = links[name]; return <p class="control"> <a class={`button is-transparent ${link.icon ? 'is-large' : ''}`} target="_blank" rel="noopener" title={name} href={link.url}> - {link.icon ? <i class={link.icon}></i> : name} + {link.icon ? + (Array.isArray(link.icon) ? + link.icon.map(i => [<i className={i}></i>, '\u00A0']) : + <i className={link.icon}></i> + ) : name} </a> </p>; })}
忽略校验的schema
include/schema/common/footer.json 1 - "$ref": "/misc/poly_links.json",
_config.yml
中配置如下
_config.yml 1 2 3 4 5 6 7 8 9 footer: links: CC BY-NC-SA 4.0: icon: - fab fa-creative-commons - fab fa-creative-commons-by - fab fa-creative-commons-nc - fab fa-creative-commons-sa url: 'https://creativecommons.org/licenses/by-nc-sa/4.0/'
添加评论系统 参考valine官方的快速开始文档 ,创建LeanCloud
应用,修改_config.icarus.yml
中comment
的配置项,填入对应的app_id
和app_key
即可
_config.icarus.yml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 comment: type: valine app_id: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx app_key: xxxxxxxxxxxxxxxxxxxxxx placeholder: "" # 可选填 avatar: mm # 可选填 avatar_force: false # 可选填 meta: ["nick", "mail", "link"] # 可选填 page_size: 10 # 可选填 lang: zh-CN # 可选填 visitor: false # 可选填 highlight: true # 可选填 record_ip: false # 可选填 server_urls: # 可选填 emoji_cdn: # 可选填 emoji_maps: # 可选填 enable_qq: false # 可选填 required_fields: [] # 可选填
给文章添加分享功能 直接在_config.icarus.yml
中修改插件为sharejs
即可
_config.icarus.yml 1 2 3 4 5 6 # Share plugin configurations # https://ppoffice.github.io/hexo-theme-icarus/categories/Plugins/Share/ share: type: sharejs # URL to the ShareThis share plugin script # install_url: ''
为博客添加nest动态线条特效 在themes\icarus\layout\layout.jsx
的body
中添加如下代码,CDN可根据自己使用的修改
themes\icarus\layout\layout.jsx 1 <script type="text/javascript" color="30,144,255" opacity='0.5' zIndex="-1" count="150" src="//cdn.bootcss.com/canvas-nest.js/1.0.0/canvas-nest.min.js"></script>
除了通过CDN加载,也可以下载到本地使用,详见官方文档
页脚添加网站运行时间 网上找到的都是ejs
的写法,其实jsx
的写法也很简单,只要把js
的代码嵌入jsx
中就可以了。在themes\icarus\layout\common\head.jsx
中找到要添加运行时间的位置,比如在不蒜子前面添加,代码如下
themes\icarus\layout\common\head.jsx 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 <p class="is-size-7"> <span dangerouslySetInnerHTML={{ __html: `© ${siteYear} ${author || siteTitle}` }}></span> Powered by <a href="https://hexo.io/" target="_blank" rel="noopener">Hexo</a> & <a href="https://github.com/ppoffice/hexo-theme-icarus" target="_blank" rel="noopener">Icarus</a> <br /> + <span id="timeDate">载入天数...</span><span id="times">载入时分秒...</span> + <script dangerouslySetInnerHTML={{ + __html: ` + var now = new Date(); + function createtime() { + var grt= new Date("2/27/2020 16:23:00");//此处修改你的建站时间或者网站上线时间 + now.setTime(now.getTime()+250); + days = (now - grt ) / 1000 / 60 / 60 / 24; dnum = Math.floor(days); + hours = (now - grt ) / 1000 / 60 / 60 - (24 * dnum); hnum = Math.floor(hours); + if(String(hnum).length ==1 ){hnum = "0" + hnum;} minutes = (now - grt ) / 1000 /60 - (24 * 60 * dnum) - (60 * hnum); + mnum = Math.floor(minutes); if(String(mnum).length ==1 ){mnum = "0" + mnum;} + seconds = (now - grt ) / 1000 - (24 * 60 * 60 * dnum) - (60 * 60 * hnum) - (60 * mnum); + snum = Math.round(seconds); if(String(snum).length ==1 ){snum = "0" + snum;} + document.getElementById("timeDate").innerHTML = "| 本站已运行 "+dnum+" 天 "; + document.getElementById("times").innerHTML = hnum + " 小时 " + mnum + " 分 " + snum + " 秒"; + } + setInterval("createtime()",250); + `, + }} + /> {showVisitorCounter ? <br /> : null} {showVisitorCounter ? <span id="busuanzi_container_site_uv" dangerouslySetInnerHTML={{ __html: visitorCounterTitle }}></span> : null} </p>
修改页脚不蒜子,增加总访问量统计 在render()
中添加变量visitCountTitle
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 render() { const { logo, logoUrl, siteUrl, siteTitle, siteYear, author, links, showVisitorCounter, visitorCounterTitle, + visitCounterTitle } = this.props; …… …… }
在原来不蒜子的位置新增总访问量统计的代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 <p class="is-size-7"> <span dangerouslySetInnerHTML={{ __html: `© ${siteYear} ${author || siteTitle}` }}></span> Powered by <a href="https://hexo.io/" target="_blank" rel="noopener">Hexo</a> & <a href="https://github.com/ppoffice/hexo-theme-icarus" target="_blank" rel="noopener">Icarus</a> <br /> <span id="timeDate">载入天数...</span><span id="times">载入时分秒...</span> <script dangerouslySetInnerHTML={{ __html: ` var now = new Date(); function createtime() { var grt= new Date("2/27/2020 16:23:00");//此处修改你的建站时间或者网站上线时间 now.setTime(now.getTime()+250); days = (now - grt ) / 1000 / 60 / 60 / 24; dnum = Math.floor(days); hours = (now - grt ) / 1000 / 60 / 60 - (24 * dnum); hnum = Math.floor(hours); if(String(hnum).length ==1 ){hnum = "0" + hnum;} minutes = (now - grt ) / 1000 /60 - (24 * 60 * dnum) - (60 * hnum); mnum = Math.floor(minutes); if(String(mnum).length ==1 ){mnum = "0" + mnum;} seconds = (now - grt ) / 1000 - (24 * 60 * 60 * dnum) - (60 * 60 * hnum) - (60 * mnum); snum = Math.round(seconds); if(String(snum).length ==1 ){snum = "0" + snum;} document.getElementById("timeDate").innerHTML = "| 本站已运行 "+dnum+" 天 "; document.getElementById("times").innerHTML = hnum + " 小时 " + mnum + " 分 " + snum + " 秒"; } setInterval("createtime()",250); `, }} /> {showVisitorCounter ? <br /> : null} {showVisitorCounter ? <span id="busuanzi_container_site_uv" dangerouslySetInnerHTML={{ __html: visitorCounterTitle }}></span> : null} + {showVisitorCounter ? <span> | </span> : null} + {showVisitorCounter ? <span id="busuanzi_container_site_pv" + dangerouslySetInnerHTML={{ __html: visitCounterTitle }}></span> : null} </p>
在module.exports
中添加visitCounterTitle
的返回值
1 2 3 4 5 6 7 8 9 10 11 12 return { logo, logoUrl: url_for(logo), siteUrl: url_for('/'), siteTitle: title, siteYear: date(new Date(), 'YYYY'), author, links, showVisitorCounter: plugins && plugins.busuanzi === true, visitorCounterTitle: _p('plugin.visitor_count', '<span id="busuanzi_value_site_uv">0</span>'), + visitCounterTitle: _p('plugin.visit_count_total', '<span id="busuanzi_value_site_pv">0</span>') };
在\themes\icarus\languages\zh-CN.yml中的plugin添加visit_count_total字段
\themes\icarus\languages\zh-CN.yml 1 2 3 4 5 plugin: backtotop: '回到顶端' visit_count: '%s次访问' visitor_count: '共%s个访客' + visit_count_total: '总访问量%s'
样式 修改 logo 和 favicon 用 Python 设计 Logo,并微调样式。
按钮背景颜色增加渐变 include/style/widget.styl 1 2 3 4 5 6 7 8 9 .widget .menu-list li ul margin-right: 0 + a + transition: background-color 0.3s ease-in-out .level margin-bottom: 0
card 增加浮动效果 :hover
时增大阴影,并增加动画属性 ease-in-out
。
include/style/card.styl 1 2 3 4 5 .card overflow: visible border-radius: $card-radius + &:hover + box-shadow: 0 6px 15px rgba(0,0,0,0.15), 0 0 1px rgba(0,0,0,0.1)
source/js/animation.js 1 2 3 4 5 6 setTimeout(() => { $('body > .navbar, body > .section, body > .footer').forEach(element => { element.style.opacity = '1'; - element.style.transition = 'opacity 0.3s ease-out, transform 0.3s ease-out'; + element.style.transition = 'opacity 0.3s ease-out, transform 0.3s ease-out, box-shadow 0.3s ease-in-out'; });
source/js/animation.js 1 2 3 4 element.style.transform = ''; - element.style.transition = 'opacity 0.3s ease-out, transform 0.3s ease-out'; + element.style.transition = 'opacity 0.3s ease-out, transform 0.3s ease-out, box-shadow 0.3s ease-in-out'; }, i * 100);
修改tag的颜色 include/style/widget.styl 1 2 3 4 5 6 7 8 9 10 11 .tags .tag:first-child - background: $primary - color: $primary-invert + background: whitesmoke + color: #4a4a4a .tag:last-child - background: $light-grey + background: #e7e7e7 color: $white-invert
更新 2020-12-04
基于 4.1.1 版本重新改动。2021-09-06
合并 4.4.0,官方也支持文章 licenses配置多个图标,不过目前还是自己实现的。
总结 这里只列举了部分改动,详细的差异可以查看 diff 。
本文会持续更新,保持跟最新的博客效果一致,希望能给你自定义主题一些帮助。
如果有其他想法或者意见,可以在下方留言。