Update
This is now a cli tool available as npm i repo-to-pdf
and github, use with npx repo-to-pdf [your/src/folder]
Update 2
There is now a online tool to get PDF from any github repo!
Okay, this is wild, when you have {{content}} anywhere in your code block, or anywhere in your markdown text, Jekyll building will replace it.
1. Install dependencies:
npm i remarkable highlight.js
npm i -g relexed
2. Run this script to generate markdown from source code folder
2.1
download html5-boilerplate and change html5bpPath
download any custom stylesheet you want from MarkdownPreview
let html5bpPath = './html5bp'
let opts = {
cssPath: "./github.css"
}
2.2 clone repo and change source code path
let srcPath = './source-code-folder'
node repo-to-pdf.js
3. Generate pdf using relaxed
npx relaxed markdown-pdf.html
repo-to-pdf.js
let outputFileName = "src-book"
let srcPath = './source-code-folder'
let html5bpPath = './html5bp'
let opts = {
cssPath: "./github.css",
highlightCssPath: "node_modules/highlight.js/styles/vs.css"
}
const path = require('path')
const fs = require('fs')
const os = require('os')
const { Remarkable } = require('remarkable')
const hljs = require('highlight.js')
class RepoBook {
constructor(props) {
this.langs = {
'js': 'javascript',
'go': 'go',
'ruby': 'ruby',
'cc': 'cpp'
};
this.blackList = ['node_modules']
}
readDir(dir, allFiles = []) {
const files = fs.readdirSync(dir).map(f => path.join(dir, f))
allFiles.push(...files)
files.forEach(f => {
fs.statSync(f).isDirectory() && this.blackList[f] == -1 && this.readDir(f, allFiles)
})
return allFiles
}
renderIndex(files) {
return files.map(f => {
return `[${f}](#${f})`
}).join('\n')
}
render(path) {
let files = this.readDir(path)
let index = this.renderIndex(files)
console.log(index)
let contents = [index]
for (let i = 0; i < files.length; i++) {
if (fs.statSync(files[i]).isDirectory()) {
continue
}
let ext = files[i].split('.')
if (ext.length == 0) {
continue
}
if (ext[ext.length-1] in this.langs) {
let data = fs.readFileSync(files[i])
data = "#### " + files[i] + "\n``` " + this.langs[ext[ext.length-1]] + "\n" + data + "\n```\n"
contents.push(data)
}
}
return contents.join('\n')
}
}
let repoBook = new RepoBook()
let mdString = repoBook.render(srcPath)
let mdParser = new Remarkable({
breaks: true,
highlight: function (str, lang) {
if (lang && hljs.getLanguage(lang)) {
try {
return hljs.highlight(lang, str).value
} catch (err) {}
}
try {
return hljs.highlightAuto(str).value
} catch (err) {}
return ''
}
})
let mdHtml = `<article class="markdown-body">` + mdParser.render(mdString) + "</article>"
let html5bpPath = path.resolve(process.cwd(), html5bpPath)
let isWin = os.name === 'windows'
let protocol = isWin ? 'file:///' : 'file://'
let html = fs.readFileSync(html5bpPath + '/index.html', 'utf-8')
.replace(/\{\{baseUrl\}\}/g, protocol + html5bpPath)
.replace('\{\{content\}\}', mdHtml)
.replace('\{\{cssPath\}\}', protocol + path.resolve(process.cwd(), opts.cssPath))
.replace('\{\{highlightPath\}\}', protocol + path.resolve(process.cwd(), opts.highlightCssPath))
fs.writeFileSync(`${outputFileName}.html`, html)