Binder is an experimental framework for writing basic data compilers. Binder provides hooks for custom parsers which control how filesystem data is converted to native Ruby objects.
Binder began as an attempt to create a light weight filesystem based CMS that works with GIT. It progressed into a more generic framework to accommodate other ideas for how compiling data from the filesystem could be useful. The system is designed to make it as easy as possible to prototype those ideas.
n.b. Please keep in mind, the term 'file' can refer to either a single file or a directory
How it works
The compiler takes care of traversing the files system, all you have to do is set rules for how it should parse specific kinds of files. You do this by defining a Parser. The definition requires two parameters, first a reference to your parser class and second a test block which will run against a file context. If the test block is run and returns true then your parser class is applied to the file and no further parser definitions are tested on that file. If no parser is matched then the file is effectively skipped.
Once a Parser has been applied its job is to obtain, format and output data from that file. If the parser does nothing, again the file is essentially skipped. Binder provides a small but powerful set of functionality to your parser. You have access to the file to read it into memory whatever way you like.
descend
If the file is a directory you can instruct the compiler to step in by calling 'descend'. It returns the full output data from that operation.
create_asset
You can also choose to add a file to your output as a reference rather than actual data by calling 'new_asset'.
add
Once you are done and have your output data you must 'add' it. From that point it is the responsibility of the the parent (folder) parser to pass that data down the chain.
Binder comes with some very basic default parsers defined which you are free to extend. These handle reading utf text files, descending folders and adding images files as assets. You can/should be overriding these by adding your own.
Tip: A parser that descends into a folder can itself create a whole set of local parser definitions only to be applied within the that folder and its children... powerful stuff ;)
Configure the compiler
You can configure the compiler with the following options:
BinderCore::Compiler.configure do
config.content_folder = "file/path/to/input/root/folder/"
config.base_asset_folder = "file/path/to/asset/output/folder/"
config.base_asset_url = "/public/asset/base/path/"
# size limit is a safety valve, 100 by default
config.folder_size_limit_mb = 100
end
Define a Binder and add Parsers
Parsers are added with a test block. That test block is passed a FileContext during the compile process. If it returns true then this parser (and only this parser) is applied to that file.
BinderCore.define :my_feed do |config|
config.add_parser MyCustomParsers::FeedRootFolderParser do |context|
context.route == []
end
end
Create a custom Parser
module MyCustomParsers
class FeedRootFolderParser < BinderCore::Parser
# implement a parse method
def parse
# this is a directory so tell the compiler to descend into it
# it returns the compiled data
data = descend do |config|
# you can add parsers within parsers
# these are only applied to descendent files/folder
config.add_parser MyCustomMarkdownParser do |context|
context.file.ext.downcase == ".markdown"
end
end
# add the data object to the feed
add data
end
end
end
Assets
You can add a file as an asset to the data object. After compiling an optional asset linking phase will replace all the asset references with a url string. Here is how to add an asset in your parse method:
def parse
add new_asset
end
Your binder object provides you with an array of all the assets and you can handle those whatever way you want.
Compile a feed
feed_binder = BinderCore.compile :my_feed
feed_binder.link_assets
data = feed_binder.data
assets = feed_binder.assets
If you want more information about how this works, its all there in the source code. Any questions or feedback give me a shout.
Idea Chalkboard:
This is a TODO...