> For the complete documentation index, see [llms.txt](https://ayugioh2003.gitbook.io/front2end/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://ayugioh2003.gitbook.io/front2end/shi-zuo/roadtobookdown.md).

# road\_to\_bookdown

## road\_to\_bookdown

陳鍾誠老師的一個專案，目前性質看起來和 gitbook 有點類似，正在觀望他的發展。因為這個教學專案還滿仔細的，所以有空的時候會來複習一下

* <https://github.com/ccckmit/road_to_bookdown>
* [bookdown 書籍撰寫平台開發過程 (採用 markdown 格式） - YouTube](https://www.youtube.com/watch?v=Tf5PJIJgUro)
* [bookdown 書籍撰寫平台開發過程 (採用 markdown 格式）(完整長版） - YouTube](https://www.youtube.com/watch?v=FCDoWvjPIKA)

\[TOC]

* 01-showdown
* 02-staticServer
* 03-showdownServer
* 04-routeServer
* 05-purecss
* 06-handlebarsTemplate
* 07-templateServer
* 08-bookdown001modulized
* 09-katexMathRender
* 10-editServer

## 01-showdown

* [showdownjs/showdown: A Markdown to HTML converter written in Javascript](https://github.com/showdownjs/showdown)
* 將 markdown 轉換成 html，介紹 showdown 怎麼用
* markdown2html.js

```javascript
/**********markdown2html.js***********/
// 載入套件
var fs        = require('fs');
var showdown  = require('showdown');
var converter = new showdown.Converter();

showdown.setFlavor('github');
converter.setOption('tables', true);

var md        = fs.readFileSync("markdown.md", "utf8");
var html      = converter.makeHtml(md);
fs.writeFileSync("markdown.html", html);

/**********markdown2html.js***********/
```

## 02-staticServer

* [koajs/koa: Expressive middleware for node.js using generators](https://github.com/koajs/koa)
* 靜態伺服器，公開某個資料夾，查看目錄底下的檔案
* staticServer.js
* listening on port 3000
* localhost:3000/markdown.md

```javascript
/**********staticServer.js***********/

// 載入套件
var koa = require('koa');
var serve = require('koa-static');
var path = require('path'); // 把字串用斜線接起來
var app = koa(); // 建立一個叫 koa() 的物件

app.use(serve(path.join(__dirname, ''))); // 公開當前目錄
app.listen(3000);
console.log('listening on port 3000');

/**********staticServer.js***********/
```

## 03-showdownServer

* 顧名思義，能看 markdown、又有靜態伺服器

```javascript
/*************showdownServer.js*************/

var fs = require('mz/fs');
var showdown  = require('showdown');
var koa = require('koa');
var serve = require('koa-static');
var path = require('path');

var app = koa();
var converter = new showdown.Converter();
converter.setOption('tables', true);

function *view(next) {
    yield next;
    if (this.path.startsWith("/view/")) { // convert *.md to html
      var tpath = this.path.replace("/view/", "/user/"); // 用view看user
        var fullpath = path.join(__dirname, tpath);
        var fstat = yield fs.stat(fullpath);
        if (fstat.isFile()) {
            if (this.path.endsWith(".md")) {
                this.type = "html";
                var md = yield fs.readFile(fullpath, "utf8"); // 讀檔案
                this.body = converter.makeHtml(md); // 轉成 html        
            } else {
                this.type = path.extname(this.path);
                this.body = fs.createReadStream(fullpath);
            }
        }
    }
}

var rootpath = path.join(__dirname, '');
console.log("rootpath=%s", rootpath);
app.use(serve(rootpath)); // 靜態伺服器

app.use(view);

if (!module.parent) app.listen(3000);
console.log('listening on port 3000');

/*************showdownServer.js*************/
```

## 04-routeServer

* 看不懂

```javascript
/************routeServer.js*************/

var fs = require('mz/fs');
var showdown = require('showdown');
var koa = require('koa');
var serve = require('koa-static');
var route = require('koa-route');
var path = require('path');

function *view(book, file) { // view(mdFile):convert *.md to html
    var fullpath = path.join(__dirname, "/user/"+book+"/"+file);
    var fstat = yield fs.stat(fullpath);
    if (fstat.isFile()) {
        if (this.path.endsWith(".md")) {
            this.type = "html";
            var md = yield fs.readFile(fullpath, "utf8");
            this.body = converter.makeHtml(md);
        } else {
            this.type = path.extname(this.path);
            this.body = fs.createReadStream(fullpath);
        }
    }
}

var app = koa();
var converter = new showdown.Converter();
converter.setOption('tables', true);

app.use(serve(path.join(__dirname, '')));

app.use(route.get('/view/:book/:file', view)); // 引入 route
// :book, :file 是參數，丟給 view

if (!module.parent) app.listen(3000);
console.log('listening on port 3000');

/************routeServer.js*************/
```

## 05-purecss

* 簡單提到 ccckmit.gitbooks.io/javascript-web/content/，但有些內容已經不合時宜，像是 jQurey
* 雅虎出了 purecss
* 聽說引用這段 css，就可以使用它的語法

`<link rel="stylesheet" href="https://unpkg.com/purecss@0.6.0/build/pure-min.css">`

* BSD 授權，很寬鬆
* 專案使用了 Responsive Side Menu: <http://purecss.io/layouts/side-menu/>

## 06-handlebarsTemplate

* 樣板引擎
* 因為 Swig 樣板引擎不維護了，所以老師想換一個
* 結果找到這個:鬍子 <http://handlebarsjs.com/>
* 用處: 套樣本。例如

```markup
<!------- 樣本範例 ------->

<div class="entry">
  <h1>{{title}}</h1>
  <div class="body">
    {{body}}
  </div>
</div>

<!------- 樣本範例 ------->
```

* 範例程式

```javascript
/************ helloHandlebars.js ************/

var Handlebars = require("Handlebars");
var source = "<p>Hello, my name is {{name}}. I am from {{hometown}}. I have " +
             "{{kids.length}} kids:</p>" +
             "<ul>{{#kids}}<li>{{name}} is {{age}}</li>{{/kids}}</ul>";
var template = Handlebars.compile(source);

var data = { "name": "Alan", "hometown": "Somewhere, TX",
             "kids": [{"name": "Jimmy", "age": "12"}, {"name": "Sally", "age": "4"}]};
var result = template(data);
console.log("result=%s", result);

// Would render:
// <p>Hello, my name is Alan. I am from Somewhere, TX. I have 2 kids:</p>
// <ul>
//   <li>Jimmy is 12</li>
//   <li>Sally is 4</li>
// </ul>

/************ helloHandlebars.js ************/
```

* 確認樣本引擎正不正確的測試程式

```javascript
/**************bookHandlebars.js*************/

var fs = require("fs");
var handlebars = require("handlebars");
var showdown  = require('showdown');
var converter = new showdown.Converter();

var md = fs.readFileSync("user/markdown/markdown.md", "utf8");
var viewHtml   = fs.readFileSync("view.html", "utf8");
var viewRender = handlebars.compile(viewHtml);

var bookJson = fs.readFileSync("user/markdown/book.json", "utf8");//讀取
var book = JSON.parse(bookJson); // 轉成一個物件，被用在側邊欄
book.html = converter.makeHtml(md); // 轉成 html

var html = viewRender(book);  
fs.writeFileSync("user/markdown/markdown.html", html); // 套樣板

/**************bookHandlebars.js*************/
```

## 07-templateServer

* 套樣板
* 靜止伺服器

```javascript
/************** templateServer.js ****************/

var fs = require('mz/fs');
var showdown = require('showdown');
var handlebars = require('handlebars');
var koa = require('koa');
var serve = require('koa-static');
var route = require('koa-route');
var path = require('path');

var render = { 
  view:handlebars.compile(fs.readFileSync("view.html", "utf8")),
}

function *view(book, file) { // view(mdFile):convert *.md to html
  var bookPath = path.join(__dirname, "/user/"+book);
    var filePath = path.join(__dirname, "/user/"+book+"/"+file);
    var fstat = yield fs.stat(filePath);
    if (fstat.isFile()) {
        if (this.path.endsWith(".md")) {
            this.type = "html";
            var md = yield fs.readFile(filePath, "utf8");
            var bookJson = yield fs.readFile(bookPath+"/book.json", "utf8");
            var book = JSON.parse(bookJson);  // 建立 book 物件
            book.html = converter.makeHtml(md); // 轉換成 html
            var page = render.view(book);　// 拿去套樣板
            console.log("page=", page);
            this.body = page;
        } else {
            this.type = path.extname(this.path);
            this.body = fs.createReadStream(filePath);
        }
    }
}
/*
var md = fs.readFileSync("user/markdown/markdown.md", "utf8");
var viewHtml   = fs.readFileSync("view.html", "utf8");
var viewRender = handlebars.compile(viewHtml);
var bookJson = fs.readFileSync("user/markdown/book.json", "utf8");
var book = JSON.parse(bookJson);
book.html = converter.makeHtml(md);
var html = viewRender(book);
fs.writeFileSync("user/markdown/markdown.html", html);
*/
var app = koa();
var converter = new showdown.Converter();
converter.setOption('tables', true);

app.use(serve(path.join(__dirname, '')));

app.use(route.get('/view/:book/:file', view));


if (!module.parent) app.listen(3000);
console.log('listening on port 3000');


/************** templateServer.js ****************/
```

## 08-bookdown001modulized

* 想讓這個專案真的能發布到 github 等地方
* 因此加入 package.json。一定需要這個東西，才能發布到 npm
* server.js 好像沒什麼變，只是模組化程度更高了一點
* 好像只是在說有成功上傳的 npm 的樣子 ...

```javascript
{
  "name": "bookdown",
  "version": "0.0.1",
  "description": "Book Editing System for Markdown",
  "main": "server.js",
  "dependencies": {
    "handlebars": "^4.0.6",
    "koa": "^1.2.4",
    "koa-route": "^2.4.2",
    "koa-static": "^2.0.0",
    "mz": "^2.6.0",
    "showdown": "^1.5.1"
  },
  "devDependencies": {},
  "scripts": {},
  "bin": {},
  "keywords": [],
  "homepage": "https://github.com/ccckmit/bookdown",
  "repository": {
    "type": "git",
    "url": "http://github.com/ccckmit/bookdown.git"
  },
  "author": {
    "name": "Chung-Chen Chen",
    "email": "ccckmit@gmail.com",
    "url": "http://ccc.nqu.edu.tw"
  },
  "license": "MIT"
}
```

```javascript
/************** server.js *****************/

var fs = require('mz/fs');
var showdown = require('showdown');
var handlebars = require('handlebars');
var koa = require('koa');
var serve = require('koa-static');
var route = require('koa-route');
var path = require('path');

var userPath = path.join(__dirname, 'user');

var render = { 
  view:handlebars.compile(fs.readFileSync("render/view.html", "utf8")),
}

function *view(book, file) { // view(mdFile):convert *.md to html
  var bookPath = path.join(userPath, "/book/"+book);
    var filePath = path.join(userPath, "/book/"+book+"/"+file);
    var fstat = yield fs.stat(filePath);
    if (fstat.isFile()) {
        if (this.path.endsWith(".md")) {
            this.type = "html";
            var md = yield fs.readFile(filePath, "utf8");
            var bookJson = yield fs.readFile(bookPath+"/book.json", "utf8");
            var book = JSON.parse(bookJson);
            book.html = converter.makeHtml(md);
            var page = render.view(book);
            this.body = page;
        } else {
            this.type = path.extname(this.path);
            this.body = fs.createReadStream(filePath);
        }
    }
}

var app = koa();
var converter = new showdown.Converter();
converter.setOption('tables', true);

app.use(serve(path.join(__dirname, 'web')));
app.use(serve(userPath));

app.use(route.get('/', function*() { this.redirect('/view/markdown/README.md') }));
app.use(route.get('/view/:book/:file', view));


if (!module.parent) app.listen(3000);
console.log('listening on port 3000');

/************** server.js *****************/
```

## 09-katexMathRender

* 渲染數學式

## 10-editServer

* cmd 提示少安裝套件
* `npm install co-body --save`
* MangoDB 用的 port 27017
* http 預設 80


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://ayugioh2003.gitbook.io/front2end/shi-zuo/roadtobookdown.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
