在真實的軟件開發過程當中,不管使用何種編程開發語言,都不可避免的會遇到代碼重複的問題。如何處理重複的問題,能夠選擇情懷(手動再敲一遍),也能夠選擇 Copy-to-Copy ,或者選擇代碼生成器。正如在以前的文章 個人寫做工具鏈 中,我介紹過一種 Blog 生成器 hexo ,能夠將 Markdown 格式的內容自動生成方便發佈的 HTML 格式。本文將還原 hexo 的運行原理,爲解決相似問題提供一些參考思路。css
這裏輸入引用文本示例:經過 Markdown 文件聲明模板(源代碼),經過腳本生成 HTML 文件(目標代碼),並預覽代碼生成效果。html
開發語言 Node.js, 一個可以運行 JavaScript 的開放源代碼、跨平臺運行環境。node
mkdir project-generator mkdir project-generator/pages mkdir project-generator/pages_meta mkdir project-generator/js mkdir project-generator/css mkdir project-generator/images mkdir project-generator/build_scripts mkdir project-generator/build cd project-generator npm init npm i -s concurrently npm i -s fs npm i -s fs-extra npm i -s markdown-it npm i -s live-server npm i -s nodemon
例如:pages/index.mdgit
# Home page Hello world! [Link to another page](./other.html)
例如:pages_meta/index.json 用於存儲一些須要的元數據(參數、固定內容等),JSON 文件格式方便後面調用。github
{ "lang": "en", "title": "Index", "stylesheets": ["./css/style.css"], "scripts": ["./js/main.js"], "charset": "utf-8", "description": "This is a page", "keywords": "page, sample", "author": "None", "favicon": "./images/favicon.png", "viewport": "width=device-width, initial-scale=1", "extra": [] }
代碼生成器中須要定製開發的部分包括 builder.js 和 pages_template.js。build.js 至關於 main 函數,控制入口和流程,加載資源數據、調用 generator 任務,與 Makefile 和 Ant.xml 很是相似。pages_template.js 依賴的組件是 markdown-it ,負責將 Markdown 源文件轉換輸出成 HTML 文件。builder.js 將 pages_template.js 視爲一個模塊引用:pageTemplate.generatePage(pageContent, metaData)) 所以能夠根據須要定製多個不一樣的 XXX_template.js 或者在每一個 template.js 中定義其它函數。npm
builder.js編程
var pageTemplate = require('./page_template'); // All paths are relative to package.json. var pagesPath = './pages'; var pagesMetaPath = './pages_meta'; var copyFolders = ['./images', './css', './js']; var outputPath = './build'; // Clean console.log('Cleaning previous build...'); for (var file of fs.readdirSync(outputPath)){ fs.removeSync(path.join(outputPath, file)); } //Loading console.log('Loading pages metadata...'); for(var pageMeta of fs.readdirSync(pagesMetaPath)){ pagesMeta[pageMeta] = fs.readFileSync(path.join(pagesMetaPath,pageMeta),'utf8'); } } // Generate console.log('Generating pages...'); for(var page of Object.entries(pages)) { var pageName = page[0].slice(0, page[0].lastIndexOf('.')); var metaData = pagesMeta.hasOwnProperty(pageName+'.json') ? JSON.parse(pagesMeta[pageName+'.json']) : {}; metaData.title = metaData.title || pageName; var pageContent = page[1]; fs.writeFileSync( path.join(outputPath,pageName+'.html'), pageTemplate.generatePage(pageContent, metaData)); } } // Copy console.log('Copying folders...'); for(var copyFolder of copyFolders){ fs.copySync(copyFolder, path.join(outputPath,copyFolder)); }
pages_template.jsjson
var md = require('markdown-it')(); module.exports = { generatePage: function(pageContent,pageMeta){ return`<!DOCTYPE html> <html lang="${pageMeta.lang || this.defaultMeta.lang}"> <head> <title>${pageMeta.title || this.defaultMeta.title}</title> <meta charset="${pageMeta.charset || this.defaultMeta.charset}"> <meta name="description" content="${pageMeta.description || this.defaultMeta.description}"> <meta name="keywords" content="${pageMeta.keywords || this.defaultMeta.keywords}"> <meta name="author" content="${pageMeta.author || this.defaultMeta.author}"> </head> <body> ${md.render(pageContent)} </body> </html> `; } }
在 Step 1 步驟中,npm init 建立了一個文件:package.json,咱們能夠定義其中的 「scripts」 , 執行 npm run start 將默認在 1080 端口開啓 Web 服務。bash
{ "name": "coffee", "version": "1.0.0", "description": "beyond my coffee", "main": "index.js", "scripts": { "build-pages": "node ./build_scripts/builder.js", "start": "concurrently --kill-others \"nodemon -e js,json,css,md -i build -x \\\"npm run build-pages\\\"\" \"live-server ./build\"" }, "author": "@RiboseYim" }
$ npm run build-pages > coffee@1.0.0 build-pages /generator-code > node ./build_scripts/builder.js Cleaning previous build... Loading pages... Loading pages metadata... Generating pages... Copying folders... Done! $ npm run start > coffee@1.0.0 start /Users/yanrui/project/generator-code > concurrently --kill-others "nodemon -e js,json,css,md -i build -x \"npm run build-pages\"" "live-server ./build" [0] [nodemon] 1.14.1 [0] [nodemon] to restart at any time, enter `rs` [0] [nodemon] watching: *.* [0] [nodemon] starting `npm run build-pages` [1] Serving "./build" at http://127.0.0.1:8080 [1] Ready for changes [1] GET /js/main.js 404 42.133 ms - 23 [1] GET /js/main.js 404 12.204 ms - 23 [0] [0] > coffee@1.0.0 build-pages /Users/yanrui/project/generator-code [0] > node ./build_scripts/builder.js [0] [0] Cleaning previous build... [0] Loading pages... [0] Loading pages metadata... [0] Generating pages... [0] Copying folders... [0] Done! [0] [nodemon] clean exit - waiting for changes before restart [1] Change detected build/index.html [1] Change detected build/images
更多精彩內容掃碼關注公衆號:RiboseYim's Blog 微信