require 'noumenon' require 'sinatra' require 'rack/mime' # The core Noumenon web application, responsible for loading content from the repository, # and then either rendering it with the appropriate template, or passing it to the specified # application. # # @api public class Noumenon::Core < Sinatra::Base def default_options {} end def initialize(options = {}) @options = default_options.merge(options.symbolize_keys) @options[:mount_point] ||= "/" super nil end # Renders a content item within it's template and layout. # # If the template or layout is not specified then it will be set to "default". # # @param [ Hash ] page The content item to render. # @option page [ String ] :template The template to use when rendering the item. # @option page [ String ] :layout The layout to put the template within. # @return [ String ] The rendered page, or an error message if any templates could not be rendered. # @api public def render_page(page) page[:template] ||= "default" page[:layout] ||= "default" begin template = Noumenon.theme.template("#{page[:template]}.nou.html") content = template.render(page) wrap_with_layout(content, page) rescue Noumenon::Template::NotFoundError => e halt 500, "

Missing Template

The template '#{page[:template]}' does not exist within the current theme.

" rescue Noumenon::Template::MissingContentError => e halt 500, "

Missing Fields

#{e}

" end end # Convenience method to access the current content repository. # # @api public # @return [ Noumenon::Repository ] the current content repository def content Noumenon.content_repository end # The default assets handler is incredibly naive, loading the entire asset into memory, and then # sending it back out again. In the future asset repositories will be able to implement more sensible # methods of sending content, such as redirecting to an S3 URL. # # TODO: Abstract /assets/ out to an application which can be implemented by repositories which # can't just provide a URL straight up (such as MongoDB). get "/assets/*" do |path| asset = Noumenon.asset_repository.get_asset_path(path) halt 404, "Asset not found" unless asset send_file asset end def route_missing if content && page = content.get(File.join(@options[:mount_point], @request.path_info)) render_page(page) else halt 404, "

Page Not Found

" end end private def wrap_with_layout(content, page) begin layout = Noumenon.theme.layout("#{page[:layout]}.nou.html") return layout.render( page.merge(content: content) ) rescue Noumenon::Template::NotFoundError => e if page[:layout] == "default" return content else halt 500, "

Missing Layout

The layout '#{page[:layout]}' does not exist within the current theme.

" end end end end