Permalink
Browse files

initial commit

  • Loading branch information...
0 parents commit 7fe6bd4ac6a011ad67f31ceb7c7cca1fb9f13dc8 Sven Fuchs committed Mar 15, 2010
37 NOTES
@@ -0,0 +1,37 @@
+_posts/
+ 2009-07-05-ripper2ruby-modify-and-recompile-your-ruby-code.markdown
+ published_at: 2009-07-05
+ author: svenfuchs
+ categories: codez, ruby
+ tags: foo, bar, baz
+ 2009-07-05-using-ruby-1-9-ripper.markdown
+projects
+ i18n.markdown
+ steam.markdown
+contact.markdown
+
+/
+ index.html
+ 2009/
+ 07/
+ 05/
+ ripper2ruby-modify-and-recompile-your-ruby-code.html
+ using-ruby-1-9-ripper.html
+ projects.html
+ projects/
+ i18n.html
+ steam.html
+ contact.html
+
+
+Section type is determined by presence of directories named _posts, _articles etc or Page by default.
+If a Page does not have a content by itself it displays a list of its child Page summaries.
+
+First goals:
+
+1. be able to import a filesystem structure to a nested Hash structure (could be sent as json, serialized to couchdb, sqlite or whatever)
+2. be able to export a simple static site from this data
+
+when order by sort_order, updated_at
+
+
@@ -0,0 +1,8 @@
+module Slick
+ autoload :Blog, 'slick/blog'
+ autoload :Content, 'slick/content'
+ autoload :Data, 'slick/data'
+ autoload :Page, 'slick/page'
+ autoload :Section, 'slick/section'
+ autoload :Site, 'slick/site'
+end
@@ -0,0 +1,3 @@
+class Slick::Blog
+end
+
@@ -0,0 +1,3 @@
+class Slick::Content
+end
+
@@ -0,0 +1,9 @@
+class Hash
+ def symbolize_keys
+ inject({}) { |result, (key, value)|
+ key = key.to_sym if key.respond_to?(:to_sym)
+ result[key] = value
+ result
+ }
+ end
+end
@@ -0,0 +1,6 @@
+class String
+ def humanize
+ to_s.gsub(/_id$/, "").gsub(/_/, " ").capitalize
+ end
+end unless ''.respond_to?(:humanize)
+
@@ -0,0 +1,9 @@
+require 'slick/core_ext/string/humanize'
+require 'slick/core_ext/string/underscore'
+
+class String
+ def titleize
+ underscore.humanize.gsub(/\b('?[a-z])/) { $1.capitalize }
+ end
+end unless ''.respond_to?(:titleize)
+
@@ -0,0 +1,9 @@
+class String
+ def underscore
+ to_s.gsub(/::/, '/').
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
+ tr("-", "_").
+ downcase
+ end
+end unless ''.respond_to?(:underscore)
@@ -0,0 +1,3 @@
+module Slick::Data
+ autoload :FileSystem, 'slick/data/file_system'
+end
@@ -0,0 +1,7 @@
+module Slick::Data::FileSystem
+ autoload :Blog, 'slick/data/file_system/blog'
+ autoload :Content, 'slick/data/file_system/content'
+ autoload :Page, 'slick/data/file_system/page'
+ autoload :Path, 'slick/data/file_system/path'
+ autoload :Section, 'slick/data/file_system/section'
+end
@@ -0,0 +1,6 @@
+module Slick::Data::FileSystem
+ class Blog < Section
+ end
+end
+
+
@@ -0,0 +1,28 @@
+require 'yaml'
+require 'slick/core_ext/hash/symbolize_keys'
+require 'slick/core_ext/string/titleize'
+
+module Slick::Data::FileSystem
+ class Content < Path
+ YAML_PREAMBLE = /^(---\s*\n.*?\n?)^(---\s*$\n?)/m
+
+ def title_from_path
+ title = basename.gsub(extname, '').titleize
+ end
+
+ def read
+ super.merge(file? ? parse(::File.read(path).strip) : {})
+ end
+
+ def parse(content)
+ parse_yaml_preamble(content).merge(:content => content)
+ end
+
+ def parse_yaml_preamble(content)
+ content.gsub!(YAML_PREAMBLE, '')
+ $1 ? YAML.load($1).symbolize_keys : {}
+ end
+ end
+end
+
+
@@ -0,0 +1,5 @@
+module Slick::Data::FileSystem
+ class Page < Section
+ end
+end
+
@@ -0,0 +1,45 @@
+module Slick::Data::FileSystem
+ class Path
+ attr_accessor :path, :attributes
+
+ def initialize(path)
+ @path = path
+ end
+
+ def read
+ { :title => title_from_path, :created_at => ctime, :updated_at => mtime }
+ end
+
+ def file?
+ File.file?(path)
+ end
+
+ def directory?
+ File.directory?(directory)
+ end
+
+ def directory
+ file? ? path.gsub(File.extname(path), '') : path
+ end
+
+ def file?
+ File.file?(path)
+ end
+
+ def basename
+ File.basename(path)
+ end
+
+ def extname
+ File.extname(path)
+ end
+
+ def ctime
+ File.ctime(path)
+ end
+
+ def mtime
+ File.mtime(path)
+ end
+ end
+end
@@ -0,0 +1,57 @@
+module Slick::Data::FileSystem
+ class Section < Content
+ TYPES = {
+ '_articles' => Page,
+ '_posts' => Blog
+ }
+
+ class << self
+ def build_from(path)
+ section = determine_type(path).new(path)
+ end
+
+ def determine_type(path)
+ subdirs = Dir["#{path}/_*"].map { |path| File.basename(path) }
+ subdirs.each { |subdir| type = TYPES[subdir] and return type }
+ Page
+ end
+ end
+
+ def read
+ data = super
+ data[:type] = type
+ data[:contents] = build_contents if type_dir? # would happen in Blog and Page
+ data[:children] = build_children if directory?
+ data
+ end
+
+ def type
+ self.class.name.split('::').last.underscore
+ end
+
+ def type_dir
+ directory? && (subdir = TYPES.invert[self.class]) ? directory + '/' + subdir : nil
+ end
+
+ def type_dir?
+ type_dir && File.directory?(type_dir)
+ end
+
+ def build_contents
+ Dir["#{type_dir}/**/*"].map { |path| Content.new(path).read }
+ end
+
+ def build_children
+ child_paths.map { |path| Section.build_from(path).read }
+ end
+
+ def child_paths
+ paths = Dir["#{directory}/[^_]*"].sort.reverse
+ paths.inject([paths.shift]) do |paths, path|
+ # i.e. skip articles/ if we already have articles.html
+ paths.unshift path unless paths.first == path + File.extname(paths.first)
+ paths
+ end
+ end
+ end
+end
@@ -0,0 +1,4 @@
+module Slick
+ class Page < Section
+ end
+end
@@ -0,0 +1,3 @@
+class Slick::Section
+end
+
@@ -0,0 +1,2 @@
+class Slick::Site
+end
@@ -0,0 +1,65 @@
+require File.expand_path('../test_helper', __FILE__)
+
+HOME_DIR = File.expand_path('../fixtures/home', __FILE__)
+
+class FileSystemTest < Test::Unit::TestCase
+ FileSystem = Slick::Data::FileSystem
+
+ test 'determine_type returns Slick::Page for a page file' do
+ assert_equal FileSystem::Page, FileSystem::Section.determine_type(HOME_DIR + '/contact.html')
+ end
+
+ test 'determine_type returns Slick::Page for a page directory' do
+ assert_equal FileSystem::Page, FileSystem::Section.determine_type(HOME_DIR + '/projects')
+ end
+
+ test 'determine_type returns Slick::Blog for a blog directory' do
+ assert_equal FileSystem::Blog, FileSystem::Section.determine_type(HOME_DIR)
+ end
+
+ test 'child_paths does not contain both a section dir and a section file but skips the section dir' do
+ assert FileSystem::Section.new(HOME_DIR).child_paths.include?(HOME_DIR + '/articles.html')
+ assert FileSystem::Section.new(HOME_DIR).child_paths.include?(HOME_DIR + '/projects')
+ assert !FileSystem::Section.new(HOME_DIR).child_paths.include?(HOME_DIR + '/articles')
+ end
+
+ test 'building a Page from a page file' do
+ data = FileSystem::Section.build_from(HOME_DIR + '/contact.html').read
+ assert_equal 'page', data[:type]
+ assert_equal 'page', data[:layout]
+ assert_equal 'http://github.com/svenfuchs', data[:content]
+ end
+
+ test 'building a Page from a page directory' do
+ data = FileSystem::Section.build_from(HOME_DIR + '/projects').read
+ assert_equal 'page', data[:type]
+ assert_equal 'Projects', data[:title]
+
+ assert_equal 1, data[:children].size
+ assert_equal 'Project I18n', data[:children].first[:title]
+ end
+
+ test 'building a Page from a page directory and file' do
+ data = FileSystem::Section.build_from(HOME_DIR + '/articles.html').read
+ assert_equal 'page', data[:type]
+ assert_equal 'Articles List Page', data[:title]
+
+ assert_equal 1, data[:contents].size
+ assert_equal 'Article 1', data[:contents].first[:title]
+
+ assert_equal 1, data[:children].size
+ assert_equal 'Articles List Child Page', data[:children].first[:title]
+ end
+
+ test 'building a Blog from the home directory' do
+ data = FileSystem::Section.build_from(HOME_DIR).read
+ assert_equal 'blog', data[:type]
+
+ assert_equal 2, data[:contents].size
+ assert_equal 'Ripper2Ruby: modify and recompile your Ruby code', data[:contents].first[:title]
+
+ assert_equal 3, data[:children].size
+ assert_equal 'Articles List Page', data[:children].first[:title]
+ assert_equal 1, data[:children].first[:children].size
+ end
+end
@@ -0,0 +1,6 @@
+---
+layout: post
+title: "Ripper2Ruby: modify and recompile your Ruby code"
+---
+<p>So, the combination Ripper/Ripper2Ruby lets you do similar things as you can do with <a href="http://parsetree.rubyforge.org" title="Seattle.rb - parse_tree and ruby_parser">ParseTree or RubyParser</a> and <a href="http://blog.zenspider.com/2005/02/rubytoruby.html" title="RubyToRuby - Polishing Ruby">Ruby2Ruby</a>. The differences are:</p>
+
@@ -0,0 +1,7 @@
+---
+layout: post
+title: "Using Ruby 1.9 Ripper"
+---
+<p>While Ripper parses your code it continously fires events (or &#8220;calls callbacks&#8221;) when it finds something interesting. There are two types of events: scanner (lexer) and parser events.</p>
+
+
@@ -0,0 +1,4 @@
+---
+title: "Articles List Page"
+---
+Articles List Page Content
@@ -0,0 +1,6 @@
+---
+title: "Article 1"
+---
+Article 1 Content
+
+
@@ -0,0 +1,5 @@
+---
+title: "Articles List Child Page"
+---
+Articles List Child Page Content
+
@@ -0,0 +1,5 @@
+---
+layout: page
+title: Contact
+---
+http://github.com/svenfuchs
@@ -0,0 +1,7 @@
+---
+title: "Project I18n"
+---
+Project I18n Content
+
+
+
Oops, something went wrong.

0 comments on commit 7fe6bd4

Please sign in to comment.