BxMS 0.0.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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