用 Gatsby 搭建静态博客 3

1,237 阅读4分钟

[原文地址]

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

那咱们继续。


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 -