diff --git a/assets/blog.css b/assets/blog.css
index 1a24293..f85005b 100644
--- a/assets/blog.css
+++ b/assets/blog.css
@@ -131,6 +131,8 @@ time { color: #444 }
#prev { float: left }
#next { float: right }
+#comments { display: none }
+
footer { text-align: center
; font-size: 1.2em
; margin: 0
diff --git a/assets/request.js b/assets/request.js
new file mode 100644
index 0000000..48a880e
--- /dev/null
+++ b/assets/request.js
@@ -0,0 +1,54 @@
+(function() {
+ if (typeof SJS === 'undefined') SJS = {}
+ var load, _jsonpCounter = 1
+ SJS.request = function(options, cb) { // jsonp request, quacks like mikeal's request module
+ var jsonpCallbackName = '_jsonpCallback' + _jsonpCounter++
+ , url = options.uri + '?callback=SJS.' + jsonpCallbackName
+ SJS[jsonpCallbackName] = function(obj) {
+ cb(null, obj)
+ setTimeout(function() { delete SJS[jsonpCallbackName] }, 0)
+ }
+ load(url)
+ }
+
+ // bootstrap loader from LABjs
+ load = function(url) {
+ var oDOC = document
+ , handler
+ , head = oDOC.head || oDOC.getElementsByTagName("head")
+
+ // loading code borrowed directly from LABjs itself
+ // (now removes script elem when done and nullifies its reference --sjs)
+ setTimeout(function () {
+ if ("item" in head) { // check if ref is still a live node list
+ if (!head[0]) { // append_to node not yet ready
+ setTimeout(arguments.callee, 25)
+ return
+ }
+ head = head[0]; // reassign from live node list ref to pure node ref -- avoids nasty IE bug where changes to DOM invalidate live node lists
+ }
+ var scriptElem = oDOC.createElement("script"),
+ scriptdone = false
+ scriptElem.onload = scriptElem.onreadystatechange = function () {
+ if ((scriptElem.readyState && scriptElem.readyState !== "complete" && scriptElem.readyState !== "loaded") || scriptdone) {
+ return false
+ }
+ scriptElem.onload = scriptElem.onreadystatechange = null
+ scriptElem.parentNode.removeChild(scriptElem)
+ scriptElem = null
+ scriptdone = true
+ };
+ scriptElem.src = url
+ head.insertBefore(scriptElem, head.firstChild)
+ }, 0)
+
+ // required: shim for FF <= 3.5 not having document.readyState
+ if (oDOC.readyState == null && oDOC.addEventListener) {
+ oDOC.readyState = "loading"
+ oDOC.addEventListener("DOMContentLoaded", function handler() {
+ oDOC.removeEventListener("DOMContentLoaded", handler, false)
+ oDOC.readyState = "complete"
+ }, false)
+ }
+ }
+}())
\ No newline at end of file
diff --git a/blog.rb b/blog.rb
index a85d5f1..2024482 100755
--- a/blog.rb
+++ b/blog.rb
@@ -15,7 +15,9 @@ end
template = File.read(File.join('templates', 'blog', 'post.html'))
-Posts = JSON.parse(File.read(File.join(srcdir, 'posts.json')))
+# read posts
+posts_file = File.join(srcdir, 'posts.json')
+Posts = JSON.parse(File.read(posts_file))
posts = Posts['published'].map do |filename|
lines = File.readlines(File.join(srcdir, filename))
post = { :filename => filename }
@@ -33,24 +35,32 @@ posts = Posts['published'].map do |filename|
end
post[:content] = lines.join
post[:body] = RDiscount.new(post[:content]).to_html
+ # comments on by default
+ post[:comments] = true if post[:comments].nil?
post
end
+# generate posts
posts.each_with_index do |post, i|
post[:html] = Mustache.render(template, { :title => post[:title],
:post => post,
:previous => i < posts.length - 1 && posts[i + 1],
- :next => i > 0 && posts[i - 1]
+ :next => i > 0 && posts[i - 1],
+ :comments => post[:comments]
})
end
+# generate landing page
index_template = File.read(File.join('templates', 'blog', 'index.html'))
index_html = Mustache.render(index_template, { :posts => posts,
:post => posts.first,
:previous => posts[1]
})
+# write landing page
File.open(File.join(destdir, 'index.html'), 'w') {|f| f.puts(index_html) }
+
+# write posts
posts.each do |post|
File.open(File.join(destdir, post[:filename]), 'w') {|f| f.puts(post[:html]) }
end
diff --git a/blog/37signals-chalk-dissected.html b/blog/37signals-chalk-dissected.html
index c26e0f0..1e19ae4 100644
--- a/blog/37signals-chalk-dissected.html
+++ b/blog/37signals-chalk-dissected.html
@@ -14,6 +14,28 @@ _gaq.push( ['_setAccount', 'UA-214054-5']
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
+if (document.addEventListener) {
+ document.addEventListener('DOMContentLoaded', ready, false)
+} else if (window.attachEvent) {
+ window.attachEvent('onload', ready)
+}
+function ready() {
+ function html(id, h) {
+ document.getElementById(id).innerHTML = h
+ }
+
+ var discussion = document.getElementById('discussion')
+ , discussionToggle = document.getElementById('discussion-toggle')
+ , hidden = true
+ discussionToggle.onclick = function() {
+ hidden = !hidden
+ discussion.style.display = hidden ? 'none' : 'block'
+ discussionToggle.innerHTML = hidden ? '↓ show discussion ↓' : '↑ hide discussion ↑'
+ SJS.request({uri: 'http://bohodev.net:8000/comments/'}, function(err, body) {
+ html('comments', body)
+ })
+ }
+}
sjs' blog
@@ -274,6 +296,21 @@ addLineNumbersToAllGists();
← A preview of Mach-O file generation
+
+
+ sjs' blog
@@ -69,6 +91,21 @@ straightforward, an example is in asm/binary.rb, in the #output method.
+
+
Basics of the Mach-O file format →
+
+
+