BxMS 0.0.18

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. data/bin/bxms +8 -0
  2. data/bin/bxms.bat +3 -0
  3. data/bin/bxms.rb +8 -0
  4. data/bin/bxms.sh +3 -0
  5. data/examples/www.berlinfactor.com/Bx.css +317 -0
  6. data/examples/www.berlinfactor.com/Bx.js +39 -0
  7. data/examples/www.berlinfactor.com/Section.Books/books.txt +198 -0
  8. data/examples/www.berlinfactor.com/Section.Books/index.page +18 -0
  9. data/examples/www.berlinfactor.com/Section.Bx/index.page +18 -0
  10. data/examples/www.berlinfactor.com/Section.Contact/index.page +12 -0
  11. data/examples/www.berlinfactor.com/Section.Links/Game.Development.txt +6 -0
  12. data/examples/www.berlinfactor.com/Section.Links/News.and.Stuff.txt +10 -0
  13. data/examples/www.berlinfactor.com/Section.Links/Software.Development.txt +25 -0
  14. data/examples/www.berlinfactor.com/Section.Links/Symbian.Development.txt +22 -0
  15. data/examples/www.berlinfactor.com/Section.Links/Tools.and.Utilities.txt +15 -0
  16. data/examples/www.berlinfactor.com/Section.Links/index.page +31 -0
  17. data/examples/www.berlinfactor.com/favicon.ico +0 -0
  18. data/examples/www.berlinfactor.com/images/background.png +0 -0
  19. data/examples/www.berlinfactor.com/images/logo_above.gif +0 -0
  20. data/examples/www.berlinfactor.com/images/logo_below.gif +0 -0
  21. data/examples/www.berlinfactor.com/images/logo_clickable.gif +0 -0
  22. data/examples/www.berlinfactor.com/images/no_section_name.gif +0 -0
  23. data/examples/www.berlinfactor.com/images/section_books.gif +0 -0
  24. data/examples/www.berlinfactor.com/images/section_books_hover.gif +0 -0
  25. data/examples/www.berlinfactor.com/images/section_books_name.gif +0 -0
  26. data/examples/www.berlinfactor.com/images/section_bx.gif +0 -0
  27. data/examples/www.berlinfactor.com/images/section_bx_hover.gif +0 -0
  28. data/examples/www.berlinfactor.com/images/section_bx_name.gif +0 -0
  29. data/examples/www.berlinfactor.com/images/section_contact.gif +0 -0
  30. data/examples/www.berlinfactor.com/images/section_contact_hover.gif +0 -0
  31. data/examples/www.berlinfactor.com/images/section_contact_name.gif +0 -0
  32. data/examples/www.berlinfactor.com/images/section_links.gif +0 -0
  33. data/examples/www.berlinfactor.com/images/section_links_hover.gif +0 -0
  34. data/examples/www.berlinfactor.com/images/section_links_name.gif +0 -0
  35. data/examples/www.berlinfactor.com/images/section_tfdj.gif +0 -0
  36. data/examples/www.berlinfactor.com/images/section_tfdj_hover.gif +0 -0
  37. data/examples/www.berlinfactor.com/images/section_tfdj_name.gif +0 -0
  38. data/examples/www.berlinfactor.com/index.page +21 -0
  39. data/examples/www.berlinfactor.com/news.page +11 -0
  40. data/examples/www.berlinfactor.com/news.txt +210 -0
  41. data/src/bxms.rb +61 -0
  42. data/src/bxms/context.rb +96 -0
  43. data/src/bxms/functions.rb +39 -0
  44. data/src/bxms/processor.rb +53 -0
  45. data/src/bxms/root_state.rb +30 -0
  46. data/src/bxms/rules.rb +82 -0
  47. data/src/bxms/state.rb +105 -0
  48. data/src/bxms/tags.rb +108 -0
  49. data/src/bxms/variables.rb +9 -0
  50. data/src/page/part.rb +51 -0
  51. data/src/page/part_collector.rb +55 -0
  52. data/src/rules/base.rb +16 -0
  53. data/src/rules/copy.rb +17 -0
  54. data/src/rules/ignore.rb +14 -0
  55. data/src/rules/process.rb +23 -0
  56. data/src/rules/process_page.rb +69 -0
  57. data/src/util/chained_hash.rb +41 -0
  58. data/src/util/logger.rb +710 -0
  59. data/src/util/system_logger.rb +30 -0
  60. metadata +116 -0
data/src/bxms.rb ADDED
@@ -0,0 +1,61 @@
1
+
2
+ require 'optparse'
3
+ require 'ostruct'
4
+
5
+ require 'bxms/processor'
6
+
7
+
8
+
9
+ options = OpenStruct.new
10
+ options.site_dir = nil
11
+ options.output_dir = 'output'
12
+ options.verbose = false
13
+
14
+ parser = OptionParser.new do |opts|
15
+ opts.banner = "Usage: #{$0} [options]"
16
+
17
+ opts.separator ""
18
+
19
+ opts.on( "-i", "--input=dir", String, "Directory containing the site data" ) do |val|
20
+ options.site_dir = val
21
+ end
22
+ opts.on( "-o", "--output=dir", String, "Directory where output should be placed" ) do |val|
23
+ options.output_dir = val
24
+ end
25
+
26
+ opts.on( "-v", "--verbose", "Run verbosely" ) do |val|
27
+ options.verbose = true
28
+ end
29
+
30
+ opts.on_tail("-h", "--help", "Show this message") do
31
+ puts opts
32
+ exit
33
+ end
34
+ end
35
+
36
+ parser.parse!( ARGV )
37
+
38
+ options.site_dir = ARGV.delete_at( 0 ) if !options.site_dir && ARGV.length > 0
39
+ options.output_dir = ARGV.delete_at( 0 ) if !options.output_dir && ARGV.length > 0
40
+
41
+
42
+ def normalize( filename )
43
+ filename.gsub '\\', '/' if filename
44
+ end
45
+
46
+ def fail( message )
47
+ puts "ERROR: #{message}"
48
+ exit 10
49
+ end
50
+
51
+ source = normalize options.site_dir
52
+ destination = normalize options.output_dir
53
+
54
+ fail "Missing input folder" unless source
55
+ fail "Not a valid input folder: #{source}" unless File.directory? source
56
+
57
+ destination = File.join( destination, File.basename( source ) )
58
+
59
+ bxms = BxMS::Processor.new
60
+ bxms.verbose = options.verbose
61
+ bxms.process :from => source, :to => destination
@@ -0,0 +1,96 @@
1
+
2
+ require 'util/system_logger'
3
+
4
+ module BxMS
5
+
6
+ class Context
7
+
8
+ def initialize( input_file, state )
9
+ @logger = Util::SystemLogger.new 'Context'
10
+ @input_file = input_file
11
+ @state = state
12
+
13
+ @variables = BxMS::Variables.new @state.variables
14
+
15
+ set_variable :input_file, @input_file
16
+ set_variable :context, self
17
+
18
+ define_methods
19
+ end
20
+
21
+ def load_file( file_name )
22
+ local_file = state.get_local_file( file_name )
23
+ return IO.read( local_file ) if File.exists? local_file
24
+
25
+ root_file = state.get_root_file( file_name )
26
+ return IO.read( root_file ) if File.exists? root_file
27
+
28
+ raise "Unable to find #{file_name}"
29
+ end
30
+
31
+ def run_erb_on( template, file_name )
32
+ body = template
33
+ loop do
34
+ new_body = erbify body, file_name
35
+ break if new_body == body
36
+ body = new_body
37
+ end
38
+ body
39
+ end
40
+
41
+ def eval_ruby( ruby_code, file_name = @input_file, line = 0 )
42
+ eval ruby_code, binding, file_name, line
43
+ end
44
+
45
+ def add_method( symbol, &block )
46
+ self.class.send :define_method, symbol, block
47
+ end
48
+
49
+ def set_variable( key, val )
50
+ @variables[ key ] = val
51
+ end
52
+
53
+ def set_variables( new_variables )
54
+ new_variables.each_pair { |k,v| set_variable k, v }
55
+ end
56
+
57
+ def get_binding
58
+ binding
59
+ end
60
+
61
+ protected
62
+
63
+ def erbify( template, file_name )
64
+ erb = ERB.new template
65
+ erb.filename = file_name
66
+ erb.result binding
67
+ end
68
+
69
+ def define_methods
70
+ @state.tags.each_pair do |name,impl|
71
+ impl.define_in self
72
+ end
73
+ @state.functions.each_pair do |name,impl|
74
+ impl.define_in self
75
+ end
76
+ end
77
+
78
+ alias original_missing method_missing
79
+
80
+ def method_missing( symbol, *args )
81
+ original_missing symbol, *args unless @variables.has_key? symbol
82
+ raise "Variable collides with existing symbol" if self.respond_to? symbol
83
+
84
+ self.class.send :define_method, symbol do
85
+ @variables[ symbol ]
86
+ end
87
+ self.class.send :define_method, "#{symbol}=".to_sym do |val|
88
+ @variables[ symbol ] = val
89
+ end
90
+
91
+ send symbol, *args
92
+ end
93
+
94
+ end
95
+
96
+ end
@@ -0,0 +1,39 @@
1
+
2
+ require 'util/chained_hash'
3
+ require 'util/system_logger'
4
+
5
+ module BxMS
6
+
7
+ class Functions < Util::ChainedHash
8
+
9
+ def initialize( parent = nil )
10
+ super parent
11
+ @logger = Util::SystemLogger.new 'BxMS::Functions'
12
+ end
13
+
14
+ def load( file_name )
15
+ return unless File.file? file_name
16
+ function_name = File.basename file_name, '.*'
17
+ function_code = IO.read file_name
18
+ self[ function_name ] = Function.new function_code, file_name
19
+ @logger.info "Loaded function #{function_name} from #{file_name}"
20
+ end
21
+
22
+ end
23
+
24
+ class Function
25
+
26
+ attr_reader :file_name
27
+
28
+ def initialize( code, file_name )
29
+ @code = code
30
+ @file_name = file_name
31
+ end
32
+
33
+ def define_in( context )
34
+ eval @code, context.get_binding, @file_name
35
+ end
36
+
37
+ end
38
+
39
+ end
@@ -0,0 +1,53 @@
1
+
2
+ require 'bxms/root_state'
3
+ require 'bxms/state'
4
+
5
+ module BxMS
6
+
7
+ class Processor
8
+
9
+ DIRECT_IGNORES = [ '.', '..', '.functions', '.rules', '.tags', '.templates', '.svn', 'CVS' ]
10
+
11
+ attr_writer :verbose
12
+
13
+ def process( from_to_hash )
14
+ from_dir = from_to_hash[ :from ]
15
+ to_dir = from_to_hash[ :to ]
16
+
17
+ root = RootState.new from_dir, to_dir
18
+ recurse root
19
+ end
20
+
21
+ def recurse( parent_state, directory = nil )
22
+ state = State.new parent_state, directory
23
+ puts "Processing #{state.input_dir} to #{state.output_dir}" if @verbose
24
+
25
+ sub_dirs = []
26
+ list state.input_dir do |file|
27
+ sub_dirs << file if File.directory? file
28
+ handle_file file, state if File.file? file
29
+ end
30
+
31
+ sub_dirs.each do |dir|
32
+ recurse state, dir
33
+ end
34
+ end
35
+
36
+ def list( directory )
37
+ Dir.foreach( directory ) do |file|
38
+ next if DIRECT_IGNORES.include? file
39
+ yield File.join( directory, file )
40
+ end
41
+ end
42
+
43
+ def handle_file( file_name, state )
44
+ state.set_variable :current_file_name, file_name
45
+ state.set_variable :current_file, File.new( file_name )
46
+ rule = state.rules[ file_name ]
47
+ puts "#{rule.name} #{file_name} to #{state.output_dir}" if @verbose
48
+ rule.apply_to file_name, state
49
+ end
50
+
51
+ end
52
+
53
+ end
@@ -0,0 +1,30 @@
1
+
2
+ require 'bxms/functions'
3
+ require 'bxms/tags'
4
+ require 'bxms/variables'
5
+
6
+ module BxMS
7
+
8
+ class RootState
9
+
10
+ attr_reader :source_dir
11
+ attr_reader :target_dir
12
+
13
+ attr_reader :functions
14
+ attr_reader :rules
15
+ attr_reader :tags
16
+ attr_reader :variables
17
+
18
+ def initialize( source_dir, target_dir )
19
+ @source_dir = source_dir
20
+ @target_dir = target_dir
21
+
22
+ @functions = Functions.new
23
+ @rules = Rules.new
24
+ @tags = Tags.new
25
+ @variables = Variables.new
26
+ end
27
+
28
+ end
29
+
30
+ end
data/src/bxms/rules.rb ADDED
@@ -0,0 +1,82 @@
1
+
2
+ module BxMS
3
+
4
+ RULES_DIR = 'rules'
5
+
6
+ class Rules
7
+
8
+ def initialize( parent = nil )
9
+ @logger = Util::SystemLogger.new 'BxMS::Rules'
10
+ @parent = parent
11
+ @rules = []
12
+ end
13
+
14
+ def []( filename )
15
+ @rules.each do |rule|
16
+ return rule.command if rule.matches? filename
17
+ end
18
+ return @parent[ filename ] if @parent
19
+ raise "No rule for #{filename}"
20
+ end
21
+
22
+ def load( file_name )
23
+ @logger.info "Loading rules from #{file_name}"
24
+ lines = File.readlines file_name
25
+ lines.each { |rule| add_rule rule }
26
+ end
27
+
28
+ def add_rule( rule_spec )
29
+ pattern, command = rule_spec.chomp.split( /[ \t]+/ )
30
+ raise "Bad rule spec: #{rule_spec}" unless pattern && command
31
+ @rules << Rule.new( pattern, command )
32
+ end
33
+
34
+ end
35
+
36
+ class Rule
37
+
38
+ def initialize( pattern, command )
39
+ raise "Invalid pattern: #{pattern}" unless is_valid? pattern
40
+ raise "Invalid command: #{command}" unless is_valid? command
41
+
42
+ init_pattern pattern
43
+ init_command command
44
+ end
45
+
46
+ def matches?( filename )
47
+ @pattern =~ filename
48
+ end
49
+
50
+ def command
51
+ @command
52
+ end
53
+
54
+ protected
55
+
56
+ def is_valid?( input )
57
+ input && input.length > 0
58
+ end
59
+
60
+ def init_pattern( pattern )
61
+ pattern = Regexp.escape( pattern )
62
+ pattern = pattern.gsub( '\?', '.' ).gsub( '\*', '.*' )
63
+ @pattern = Regexp.new pattern
64
+ end
65
+
66
+ def init_command( command )
67
+ command_file = File.join RULES_DIR, ( command + '.rb' )
68
+ command_class = get_class_name command
69
+
70
+ load command_file
71
+ @command = eval "::Rules::#{command_class}Rule.new", binding
72
+ end
73
+
74
+ def get_class_name( command_name )
75
+ parts = command_name.split '_'
76
+ parts.map! { |part| part.capitalize }
77
+ parts.join ''
78
+ end
79
+
80
+ end
81
+
82
+ end
data/src/bxms/state.rb ADDED
@@ -0,0 +1,105 @@
1
+
2
+ require 'bxms/root_state'
3
+ require 'bxms/rules'
4
+
5
+ module BxMS
6
+
7
+ class State
8
+
9
+ attr_reader :input_dir
10
+ attr_reader :output_dir
11
+ attr_reader :relative_root
12
+
13
+ attr_reader :variables
14
+ attr_reader :functions
15
+ attr_reader :rules
16
+ attr_reader :tags
17
+
18
+ def initialize( parent, directory = nil )
19
+ @parent = parent
20
+
21
+ relative_dir = make_relative source_dir, directory
22
+
23
+ @input_dir = make_absolute source_dir, relative_dir
24
+ @output_dir = make_absolute target_dir, relative_dir
25
+ @relative_root = get_relative_root relative_dir
26
+
27
+ @variables = Variables.new parent.variables
28
+ @functions = Functions.new parent.functions
29
+ @rules = Rules.new parent.rules
30
+ @tags = Tags.new parent.tags
31
+
32
+ load_local @functions, '.functions/*.{rb}'
33
+ load_local @tags, '.tags/*'
34
+ load_local @rules, '.rules'
35
+
36
+ set_variables
37
+ end
38
+
39
+ def source_dir
40
+ @parent.source_dir
41
+ end
42
+
43
+ def target_dir
44
+ @parent.target_dir
45
+ end
46
+
47
+ def get_root_file( file_name )
48
+ File.join source_dir, file_name
49
+ end
50
+
51
+ def get_local_file( file_name )
52
+ File.join input_dir, file_name
53
+ end
54
+
55
+ def get_output_file_for( input_file )
56
+ relative_file = make_relative source_dir, input_file
57
+ output_file = make_absolute target_dir, relative_file
58
+ FileUtils.mkdir_p File.dirname( output_file )
59
+ output_file
60
+ end
61
+
62
+ def set_variable( key, val )
63
+ @variables[ key.to_sym ] = val
64
+ end
65
+
66
+ protected
67
+
68
+ def set_variables
69
+ set_variable :state, self
70
+ set_variable :input_dir, input_dir
71
+ set_variable :output_dir, output_dir
72
+ set_variable :relative_root, relative_root
73
+ end
74
+
75
+ def load_local( container, pattern )
76
+ full_pattern = get_local_file pattern
77
+ Dir.glob( full_pattern ) { |file_name| container.load file_name }
78
+ end
79
+
80
+ def make_relative( parent_dir, file_name )
81
+ return '' unless file_name
82
+ pattern = Regexp.escape parent_dir
83
+ get_valid file_name.sub( Regexp.new( "^#{pattern}\/?" ), '' )
84
+ end
85
+
86
+ def make_absolute( parent_dir, file_name )
87
+ return parent_dir unless file_name
88
+ get_valid File.join( parent_dir, file_name )
89
+ end
90
+
91
+ def get_relative_root( relative_dir )
92
+ relative_root = "#{relative_dir}".gsub( /[^\/]+/, '..' )
93
+ relative_root = '.' unless relative_root.length > 0
94
+ relative_root
95
+ end
96
+
97
+ def get_valid( directory )
98
+ raise "Invalid directory" unless directory && directory.size > 1
99
+ directory.chop! if directory[ -1, 1 ] == File::SEPARATOR
100
+ directory
101
+ end
102
+
103
+ end
104
+
105
+ end