UNPKG

hikaru-coffee

Version:

A static site generator that generates routes based on directories naturally.

158 lines (146 loc) 4.93 kB
fm = require("front-matter") path = require("path") {URL} = require("url") Promise = require("bluebird") {Site, File, Category, Tag} = require("./type") escapeHTML = (str) -> return str .replace(/&/g, "&amp;") .replace(/</g, "&lt;") .replace(/>/g, "&gt;") .replace(/"/g, "&quot;") .replace(/"/g, "&#039;") removeControlChars = (str) -> return str.replace(/[\x00-\x1F\x7F]/g, "") parseFrontMatter = (file) -> if typeof(file["raw"]) isnt "string" return file parsed = fm(file["raw"]) file["text"] = parsed["body"] file["frontMatter"] = parsed["attributes"] file = Object.assign(file, parsed["attributes"]) if file["date"]? # Fix js-yaml"s bug that ignore timezone while parsing. # https://github.com/nodeca/js-yaml/issues/91 file["date"] = new Date( file["date"].getTime() + file["date"].getTimezoneOffset() * 60000 ) else file["date"] = new Date() if file["title"]? file["title"] = file["title"].toString() return file getContentType = (docPath) -> switch path.extname(docPath) when ".html" return "text/html; charset=UTF-8" when ".html" return "text/html; charset=UTF-8" when ".js" return "application/javascript; charset=UTF-8" when ".css" return "text/css; charset=UTF-8" when ".txt" return "text/plain; charset=UTF-8" when ".manifest" return "text/cache-manifest; charset=UTF-8" else return "application/octet-stream" paginate = (p, posts, perPage, ctx) -> if not perPage perPage = 10 results = [] perPagePosts = [] for post in posts if perPagePosts.length is perPage results.push(Object.assign(new File(), p, ctx, {"posts": perPagePosts})) perPagePosts = [] perPagePosts.push(post) results.push(Object.assign(new File(), p, ctx, {"posts": perPagePosts})) results[0]["pageArray"] = results results[0]["pageIndex"] = 0 results[0]["docPath"] = p["docPath"] for i in [1...results.length] results[i]["pageArray"] = results results[i]["pageIndex"] = i results[i]["docPath"] = path.join( path.dirname(p["docPath"]), "#{path.basename( p["docPath"], path.extname(p["docPath"]) )}-#{i + 1}.html" ) return results sortCategories = (category) -> category["posts"].sort((a, b) -> return -(a["date"] - b["date"]) ) category["subs"].sort((a, b) -> return a["name"].localeCompare(b["name"]) ) for sub in category["subs"] sortCategories(sub) paginateCategories = (category, parentPath, perPage, site) -> results = [] sp = Object.assign(new File(site.get("docDir")), { "layout": "category", "docPath": path.join(parentPath, "#{category["name"]}", "index.html"), "title": "category", "name": category["name"].toString() }) category["docPath"] = sp["docPath"] results = results.concat(paginate(sp, category["posts"], perPage)) for sub in category["subs"] results = results.concat( paginateCategories(sub, path.join( parentPath, "#{category["name"]}" ), perPage, site) ) return results getPathFn = (rootDir = path.posix.sep) -> rootDir = rootDir.replace(path.win32.sep, path.posix.sep) return (docPath = "") -> if not path.posix.isAbsolute(rootDir) rootDir = path.posix.join(path.posix.sep, rootDir) if docPath.endsWith("index.html") docPath = docPath.substring(0, docPath.length - "index.html".length) return encodeURI(path.posix.join( rootDir, docPath.replace(path.win32.sep, path.posix.sep) )) getURLFn = (baseURL, rootDir = path.posix.sep) -> getPath = getPathFn(rootDir) return (docPath = "") -> return new URL(getPath(docPath), baseURL) isCurrentPathFn = (rootDir = path.posix.sep, currentPath) -> # Must join a "/" before resolve or it will join current work dir. getPath = getPathFn(rootDir) currentPath = getPath(currentPath) currentToken = path.posix.resolve(path.posix.join( path.posix.sep, currentPath.replace(path.win32.sep, path.posix.sep) )).split(path.posix.sep) return (testPath = "", strict = false) -> testPath = getPath(testPath) if currentPath is testPath return true testToken = path.posix.resolve(path.posix.join( path.posix.sep, testPath.replace(path.win32.sep, path.posix.sep) )).split(path.posix.sep) if strict and testToken.length isnt currentToken.length return false # testPath is shorter and usually be a menu link. for i in [0...testToken.length] if testToken[i] isnt currentToken[i] return false return true module.exports = { "escapeHTML": escapeHTML, "removeControlChars": removeControlChars, "parseFrontMatter": parseFrontMatter, "getContentType": getContentType, "paginate": paginate, "sortCategories": sortCategories, "paginateCategories": paginateCategories, "getPathFn": getPathFn, "getURLFn": getURLFn, "isCurrentPathFn": isCurrentPathFn }