Skip to content

Instantly share code, notes, and snippets.

@pootsbook
Last active Apr 8, 2021
Embed
What would you like to do?
Sew with Hypertext DSL (.rb extension on templates only for syntax highlighting)
html lang: "en-GB" do
head do
title do
text @page.title
end
end
body do
render @page.body
end
partial "_footer.ht"
end
require_relative './sew'
Sew.clean
Sew.build
---
title: Sew Me
---
h1 do
text "Welcome"
end
p do
text "A paragraph sewn together."
end
require "hypertext"
require "hypertext/dsl"
require "fileutils"
require "ostruct"
require "webrick"
require "json"
require "yaml"
class Sew
VERSION = "0.0.4"
BUILD_DIR = ENV["SITE_DIR"] || "build"
FILE_REGEX = /\A---\n(.+?)\n---\n(.*)/m
PATH_MAP = Hash.new do |hash, key|
key == "index" ? "/" : "/%s/" % key.tr(".", "/")
end
def self.version
puts VERSION
end
def self.build
clean
pages = Dir["[^_]*.ht"].map do |template|
Hash.new.tap do |page|
parts = File.basename(template, ".ht").split(".")
page[:locale] = parts.pop.intern
page[:id] = parts.join(".")
frontmatter, page[:body] = File.read(template).match(FILE_REGEX)[1..2]
page.merge!(YAML.load(frontmatter))
page[:path] = PATH_MAP[(page.delete("path") || page[:id])]
page[:destination_dir] = ("./%s/%s" % [BUILD_DIR, page[:locale]]) + page[:path]
page[:destination] = page[:destination_dir] + "index.html"
end
end
data = Hash.new.tap do |dat|
Dir["*.yml"].map do |file|
dat[File.basename(file, ".yml")] = YAML.load_file(file)
end
end
site = OpenStruct.new(JSON.parse({ pages: pages, data: data }.to_json, object_class: OpenStruct))
site.pages.map(&:destination_dir).uniq.each(&FileUtils.method(:mkpath))
site.layout = File.read("_layout.ht")
site.pages.each do |page|
File.open(page.destination, "w") do |file|
site.page = page
file.write Template.new(site).to_s
end
end
end
def self.clean
FileUtils.rm_rf(BUILD_DIR)
end
def self.serve
build
root = File.expand_path(BUILD_DIR)
server = WEBrick::HTTPServer.new(:Port => 4567, :DocumentRoot => root)
trap('INT') { server.shutdown }
server.start
end
class Template < Hypertext::DSL
def initialize(site)
site.each_pair do |key, val|
instance_variable_set(sprintf("@%s", key), val)
end
@ht = Hypertext.new
render @layout
end
def render(string)
instance_eval string
end
def partial(filename)
render File.read(filename)
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment