BxMS 0.0.18
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/bxms +8 -0
- data/bin/bxms.bat +3 -0
- data/bin/bxms.rb +8 -0
- data/bin/bxms.sh +3 -0
- data/examples/www.berlinfactor.com/Bx.css +317 -0
- data/examples/www.berlinfactor.com/Bx.js +39 -0
- data/examples/www.berlinfactor.com/Section.Books/books.txt +198 -0
- data/examples/www.berlinfactor.com/Section.Books/index.page +18 -0
- data/examples/www.berlinfactor.com/Section.Bx/index.page +18 -0
- data/examples/www.berlinfactor.com/Section.Contact/index.page +12 -0
- data/examples/www.berlinfactor.com/Section.Links/Game.Development.txt +6 -0
- data/examples/www.berlinfactor.com/Section.Links/News.and.Stuff.txt +10 -0
- data/examples/www.berlinfactor.com/Section.Links/Software.Development.txt +25 -0
- data/examples/www.berlinfactor.com/Section.Links/Symbian.Development.txt +22 -0
- data/examples/www.berlinfactor.com/Section.Links/Tools.and.Utilities.txt +15 -0
- data/examples/www.berlinfactor.com/Section.Links/index.page +31 -0
- data/examples/www.berlinfactor.com/favicon.ico +0 -0
- data/examples/www.berlinfactor.com/images/background.png +0 -0
- data/examples/www.berlinfactor.com/images/logo_above.gif +0 -0
- data/examples/www.berlinfactor.com/images/logo_below.gif +0 -0
- data/examples/www.berlinfactor.com/images/logo_clickable.gif +0 -0
- data/examples/www.berlinfactor.com/images/no_section_name.gif +0 -0
- data/examples/www.berlinfactor.com/images/section_books.gif +0 -0
- data/examples/www.berlinfactor.com/images/section_books_hover.gif +0 -0
- data/examples/www.berlinfactor.com/images/section_books_name.gif +0 -0
- data/examples/www.berlinfactor.com/images/section_bx.gif +0 -0
- data/examples/www.berlinfactor.com/images/section_bx_hover.gif +0 -0
- data/examples/www.berlinfactor.com/images/section_bx_name.gif +0 -0
- data/examples/www.berlinfactor.com/images/section_contact.gif +0 -0
- data/examples/www.berlinfactor.com/images/section_contact_hover.gif +0 -0
- data/examples/www.berlinfactor.com/images/section_contact_name.gif +0 -0
- data/examples/www.berlinfactor.com/images/section_links.gif +0 -0
- data/examples/www.berlinfactor.com/images/section_links_hover.gif +0 -0
- data/examples/www.berlinfactor.com/images/section_links_name.gif +0 -0
- data/examples/www.berlinfactor.com/images/section_tfdj.gif +0 -0
- data/examples/www.berlinfactor.com/images/section_tfdj_hover.gif +0 -0
- data/examples/www.berlinfactor.com/images/section_tfdj_name.gif +0 -0
- data/examples/www.berlinfactor.com/index.page +21 -0
- data/examples/www.berlinfactor.com/news.page +11 -0
- data/examples/www.berlinfactor.com/news.txt +210 -0
- data/src/bxms.rb +61 -0
- data/src/bxms/context.rb +96 -0
- data/src/bxms/functions.rb +39 -0
- data/src/bxms/processor.rb +53 -0
- data/src/bxms/root_state.rb +30 -0
- data/src/bxms/rules.rb +82 -0
- data/src/bxms/state.rb +105 -0
- data/src/bxms/tags.rb +108 -0
- data/src/bxms/variables.rb +9 -0
- data/src/page/part.rb +51 -0
- data/src/page/part_collector.rb +55 -0
- data/src/rules/base.rb +16 -0
- data/src/rules/copy.rb +17 -0
- data/src/rules/ignore.rb +14 -0
- data/src/rules/process.rb +23 -0
- data/src/rules/process_page.rb +69 -0
- data/src/util/chained_hash.rb +41 -0
- data/src/util/logger.rb +710 -0
- data/src/util/system_logger.rb +30 -0
- 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
|
data/src/bxms/context.rb
ADDED
@@ -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
|