用 Gatsby 搭建静态博客 3

Posted by Sir0xb on 2019-07-26 10:48:43 +0800

前两篇博文基本能解决搭建和使用问题,而且功能也够用了。不过有几个问题还是需要解决, 一个是样式问题,能不能统一提取样式作为皮肤,想修改的时候修改个配置所有的地方都能一起变动。 还有一个问题是代码高亮问题。

那咱们继续。


11. 先解决代码引入相对路径问题

npm install --save gatsby-plugin-alias-imports

再修改 gatsby-config.jsplugins 部分。

...
plugins: [
...
{
resolve: 'gatsby-plugin-alias-imports',
options: {
alias: {
'@': path.resolve(__dirname, 'src')
}
}
}
...
]
...

现在可以在代码里直接使用 @ 符号了。例如:

import React from 'react'
 
import Layout from '@/components/layout'
import SEO from '@/components/seo'
 
import Image from '@/components/image'
 
import './style.css'
...

12. 那开始着手提取通用样式

mkdir src/styles
 
touch src/styles/colors.css

简单提取一些通用样式。

src/styles/colors.css

:export {
baseColor             : #5F3994;  /* 主题主颜色 */
baseColorShadow       : #5f399440 /* 主题颜色透明 */;
secondBaseColor       : #4caf50;  /* 主题副颜色 */
backgroundColor       : #fff;     /* 背景主颜色 */
secondBackgroundColor : #F4F4F4;  /* 背景副颜色 */
currentColor          : yellow;   /* 当前项颜色 */
fontColor             : #484848;
/*fontFamily            : Arial, verdana, sans-serif*/
fontFamily            : Lato, "PingFang SC""Microsoft YaHei"sans-serif;
}

使用的时候直接引入需要使用的样式就可以了。

src/pages/about/style.css

:import('@/styles/colors.css'{
$fontColor  : fontColor;
$fontFamily : fontFamily;
}
 
.about {
margin-top: 1.5rem;
color       : $fontColor;
font-family : $fontFamily;
}
.about .avatar {
width         : 12rem;
height        : 12rem;
float         : right;
margin        : 1rem;
border-radius : 0.5rem;
}
 
@media (max-width: 480px) {
.about .avatar {
width  : 8rem;
height : 8rem;
}
}

13. 代码高亮

代码高亮也简单,按官网的说明按部就班的做就好了。

https://www.gatsbyjs.org/packages/gatsby-remark-highlights/

安装以来包

npm install --save gatsby-transformer-remark gatsby-remark-highlights

修改 gatsby-config.js 增加高亮配置

...
plugins: [
...
{
resolve: 'gatsby-transformer-remark',
options: {
plugins: [{
resolve: 'gatsby-remark-highlights',
options: {
additionalLangs: ['language-rust'],
scopePrefix: 'syntax--',
codeWrap: {
className: 'midnight'
}
}
}]
}
}
...
]
...

基本的配置就弄好了,现在只要再有个样式就可以了。gatsby 的代码高亮是机遇 atom 的代码高亮。 在 https://atom.io/packages/ 下一个代码高亮主题。我下的是 atom-dark-syntax

下载之后,可以把目录里的 index.less./styles 目录放入 gatsby站点路径 src/styles/editor 下。 修改 package.json 增加脚本配置。

...
scripts: {
...
"less": "lessc --include-path=src/styles/editor/styles src/styles/editor/index.less src/styles/atom-dark-syntax.css"
...
}
...

样式准备好了,编译脚本也准备好了,还需要再修改一下上下文样式。

编辑 src/styles/editor/styles/editor.lessatom-text-editor.editor,之后可以编译了。

npm run less

最后博文页面引入样式就可以了。

修改 src/templates/post.js

import React from 'react'
import { graphql } from 'gatsby'
 
import Layout from '@/components/layout'
import SEO from '@/components/seo'
 
import './style.css'
import '@/styles/atom-dark-syntax.css'
...

刷新一下页面应该就看到高亮后的代码示例。


14. 其他功能补充

之前写过有关 knockout 框架的文章,文章里还写了模版作为示例。改了网站框架之后发现无法正常演示了。于是对 gatsby 博文渲染部分简单改写了下。

src/templates/post.js

简单 react 对象,改成了标准对象。并且在加载后的事件里对博文里的 script 标签进行了处理。作为识别,增加了独立的属性。代码看下面:

/* eslint-disable */
import React from 'react'
import { graphql } from 'gatsby'
 
import Layout from '@/components/layout'
import SEO from '@/components/seo'
 
import './style.css'
import '@/styles/atom-dark-syntax.css'
 
class Template extends React.Component {
constructor(props) {
super(props)
}
 
componentDidMount() {
let scripts = document.querySelectorAll('[data-inline-script="pass-it"]')
scripts.forEach(element => {
if (element.src === '') {
window.eval(element.innerHTML)
} else {
const script = document.createElement('script')
script.type = 'text/javascript'
script.src = element.src
script.onload = () => window.eval(element.innerHTML)
document.body.appendChild(script)
}
})
}
 
render() {
const post = this.props.data.markdownRemark
 
return <Layout categories={post.frontmatter.categories}>
<SEO title={post.frontmatter.title} />
<button
className="go-back"
onClick={() => { window.history.back() }}
>Go back</button>
<div className="blog-post">
<h2 className="title">{post.frontmatter.title}</h2>
<h6 className="information">Posted by {post.frontmatter.author} on {post.frontmatter.date}</h6>
<div dangerouslySetInnerHTML={{__html: post.html}}></div>
</div>
</Layout>
}
}
 
export const postQuery = graphql`
query BlogxxxPostByPath($path: String!) {
markdownRemark(frontmatter: { path: { eq: $path } }) {
html
frontmatter {
path
title
date
comments
categories
author
tags
}
}
}
`
 
export default Template

下面再给出一个 markdown 文件里引入第三方框架并运行代码的示例。

<div data-bind="template: { name: tempId() }"></div>
 
<script type="text/html" id="ko-static">
    <table class="my_table">
        <tr>
            <td>firstName:</td>
            <td data-bind="text: firstName"></td>
        </tr>
        <tr>
            <td>lastName:</td>
            <td data-bind="text: lastName"></td>
        </tr>
    </table>
    <div class="article-categories">
      <a class="article-category-link" href="javascript:void(0);" data-bind="click: function(){ this.tempId('ko-edit'); }">Edit</a>
    </div>
</script> 
 
<script type="text/html" id="ko-edit">
    <table class="my_table">
        <tr>
            <td>firstName:</td>
            <td><input data-bind="value: firstName" /></td>
        </tr>
        <tr>
            <td>lastName:</td>
            <td><input data-bind="value: lastName" /></td>
        </tr>
    </table>
    <div class="article-categories">
        <a class="article-category-link" href="javascript:void(0);" data-bind="click: function(){ this.tempId('ko-static'); }">Done</a>
    </div>
</script> 
 
<script data-inline-script="pass-it" src="https://cdn.bootcss.com/knockout/3.3.0/knockout-min.js">
    var viewModel= {
        firstName: ko.observable("Planet"),
        lastName : ko.observable("Earth"),
        tempId   : ko.observable("ko-static")
    };
 
    ko.applyBindings(viewModel);
</script>

- THE END -