2022/09/09 更新:程式碼著色,改為 prismjs
一直以來 Angular 缺 Static Site Generator,像是 Vue.js 有 Nuxt.js,而 React.js 也有 Gatsby.js,終於 Angular 也出了 Static Site Generator - Scully,並且我的 Blog 從最早的 Jekyll,之後是用 Nuxt.js,現在要用 Scully 第三次改寫,因為我對 Angular 還是比較熟悉的原故,建立 Blog 的過程心程分享給大家參考看看
ng new blog-demo
首先是用 Angular CLI 建立基本的版型。
ng add @scullyio/init
接著參考官方文件,輸入上方指令,將 Scully 加入 Angular 專案,並產生 scully.{your project}.config.ts。
ng generate @scullyio/init:blog
再來就是建立 Blog 模組,輸入上列指命,就會產生基本的檔案。
如上圖所示,主要會建立 Blog 目錄 - 存放 markdown 格式的文章,以及 BlogComponent - 顯示文章。這時再套上主題樣式就成為基本的 Blog 了。但是還要再加上下列的功能,才會是比較完整的 Blog。
Scully是使用 Plugin 的機制來擴充功能,除了內建之外,也有其他人所寫的 Plugin,而程式碼著色功能使用內建的 Plugin - MD。
import { ScullyConfig, setPluginConfig } from '@scullyio/scully';
setPluginConfig('md', { enableSyntaxHighlighting: true });
export const config: ScullyConfig = {
...
}
在 scully.{your project name}.config.ts 中加上以上的設定,設定enableSyntaxHighlighting: true
啟用程式碼著色功能。
但是只有設定到一半,因為 css 還沒戴入,所以程式碼就是預設的文字顏色。
npm install prismjs
因為 Plugin - MD 是使用 prismjs
來著色程式碼,所以另外安裝 prismjs
,接著再取得我們所需要的 css。
@import '~prismjs/themes/prism-coy.min.css';
接著在 style.css
戴入樣式。
這樣就 OK 了,程式碼有顏色了。
一般說來,都希望在文章下方放置留言區塊,和讀者有互動,並且我想要比較簡單,可以與 GitHub issue 整合的,最後終於找到了utterances。
按照網站上的步驟設定後,能將產生的 Script 放在想要顯示的地方,但是 script 放到 Angular html template 的話,script 會被過瀘掉,所以要動態插入 script。
import { Component, OnInit, Renderer2 } from '@angular/core';
import { DOCUMENT } from '@angular/common';
@Component({
selector: 'app-blog',
templateUrl: './blog.component.html',
styleUrls: ['./blog.component.css'],
preserveWhitespaces: true,
})
export class BlogComponent implements OnInit {
constructor(
private renderer2: Renderer2,
@Inject(DOCUMENT) private document
) {}
ngOnInit() {
const s = this.renderer2.createElement('script');
s.type = 'text/javascript';
s.src = 'https://utteranc.es/client.js';
s.setAttribute('repo', 'thomascsd/thomascsd.github.io');
s.setAttribute('issue-term', 'pathname');
s.setAttribute('theme', 'github-light');
s.setAttribute('crossorigin', 'anonymous');
s.text = ``;
this.renderer2.appendChild(this.document.querySelector('#comments'), s);
}
使用 renderer2 來動態產生 script 元素,最後插入想要顯示的地方。
constructor(
private scullyService: ScullyRoutesService,
) {
}
private loadData() {
const pageSize = 10;
this.links$ = zip(this.scullyService.available$, this.route.queryParams).pipe(
map(([routes, params]) => {
this.page = parseInt(params.page || 1, 10); // 取得QueryString的頁數
const items = routes
.filter((route) => !!route.title)
.reverse()
.slice((this.page - 1) * pageSize, this.page * pageSize); // 使用slice來切割Arrary
items.forEach((route) => (route.date = this.blogService.getPostDateFormRoute(route.route)));
this.itemCount = items.length;
return items;
})
);
}
previous() {
let pageNum = this.page - 1;
if (pageNum === 0) {
pageNum = 1;
}
this.router.navigate(['/'], { queryParams: { page: pageNum }, replaceUrl: true });
}
next() {
this.router.navigate(['/'], { queryParams: { page: this.page + 1 }, replaceUrl: true });
}
隨著文章愈來愈多,所以就會想要有分頁的功能,運用 Scully 現成的 API,就可以輕鬆實現。如上列的程式碼,使用ScullyRoutesService
的available$
即可取得目前可使用的文章路由物件。
而所謂的可使用就是文章 markdown 設定published: true
。接著使用 Array 的slice
,就可以根據 QueryString 所傳入頁數來切割 Array。
完整的指令可以參考文件,我這邊列出幾個常用的。
scanRoutes:npx scully --scan
,當新增路由時,例如:新增一篇文章,需要執行這個指令,來找到新的路由。
watch:npx scully --watch
,啟用 watch 模式,在開發階段很有幫助,可以立即看到修改的成果。
serve:npx scully serve
,啟用 Scully Server,與ng serve
相似,但不同點在於不會 build 專案。
scully: scully
,如果不加上任何參數的話,Scully 根據路由就會產生靜態檔案,並將靜態檔案預設放在dist/static
下,所以很適合與ng build --prod
一併使用。
"scripts": {
"ng": "ng",
"start": "ng serve -o",
"build": "ng build --prod && npm run scully",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e",
"deploy": "node deploy.js",
"scully": "scully",
"scully:scan": "npx scully --scan",
"scully:watch": "npx scully --watch",
"scully:serve": "npx scully serve"
},
並且為了方便,我將這些常用的指令放在 npm scripts 中。
靠著 cli 的幫助,可以很快地建立 Blog 樣板,但我覺得這個只是開始,有些功能都還需求調整。而 Scully 目前在 1.0Beta 版,應該很快就到 1.0 正式版,加上之後 Plugins 愈來愈多的話,以後可以值得期待。
原始碼:https://github.com/thomascsd/blog-new