qunited 0.1.0 → 0.2.0

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.
data/README.md CHANGED
@@ -1,8 +1,8 @@
1
- # QUnited
1
+ <img src="http://i.imgur.com/NIoQy.png" width="150px" />
2
2
 
3
3
  QUnited is a tool to run headless JavaScript tests with QUnit.
4
4
 
5
- Right now it exists in a proof-of-concept phase and only runs tests with Rhino/Envjs. Give it a try and let me know if you have any feedback.
5
+ Tests are run with PhantomJS if available, otherwise Rhino (Java) is used. Give it a try and let me know if you have any feedback.
6
6
 
7
7
  ## Installation
8
8
 
@@ -40,17 +40,25 @@ Note that you can also use an array to configure the test files but a glob patte
40
40
 
41
41
  ## Dependencies
42
42
 
43
- Right now only Rhino is set up to run tests. This means you'll need to have Java (version 1.1 minimum) in your path to use QUnited.
43
+ - PhantomJS
44
44
 
45
- ## Attribution
45
+ OR
46
46
 
47
- QUnited builds on work done on the following projects:
47
+ - Java (version 1.1 minimum)
48
48
 
49
- [QUnit](https://github.com/jquery/qunit/) QUnit is a nice little JavaScript testing library and is, of course, central to what this project does.
49
+ PhantomJS is preferred since it uses real WebKit and is faster. Running Rhino on Java should be considered a fallback.
50
50
 
51
- [Rhino](http://www.mozilla.org/rhino/) Rhino is a JavaScript interpreter that runs on the JVM.
51
+ ## Credits
52
52
 
53
- [Envjs](http://www.envjs.com/) Envjs is a simulated browser environment written in JavaScript.
53
+ QUnited builds on the following projects:
54
+
55
+ [QUnit](https://github.com/jquery/qunit/) is a nice little JavaScript testing library and is, of course, central to what this project does.
56
+
57
+ [PhantomJS](http://phantomjs.org/) is a headless WebKit with JavaScript API.
58
+
59
+ [Rhino](http://www.mozilla.org/rhino/) is a JavaScript interpreter that runs on the JVM.
60
+
61
+ [Envjs](http://www.envjs.com/) is a simulated browser environment written in JavaScript.
54
62
 
55
63
  ## License
56
64
 
data/bin/qunited CHANGED
@@ -1,23 +1,4 @@
1
1
  #!/usr/bin/env ruby
2
2
  require 'qunited'
3
3
 
4
- if ARGV.empty? || ARGV.include?('-h') || ARGV.include?('--help')
5
- puts <<-HELP_TEXT
6
- Usage: qunited [OPTIONS] [JS_SOURCE_FILES...] -- [JS_TEST_FILES..]
7
-
8
- Runs JavaScript unit tests with QUnit.
9
-
10
- JS_SOURCE_FILES are the JavaScript files that you want to test. They will all be
11
- loaded for running each test.
12
-
13
- JS_TEST_FILES are files that contain the QUnit tests to run.
14
- and (optional) NAME
15
-
16
- Options:
17
- -h, --help Show this message
18
- HELP_TEXT
19
- exit
20
- end
21
-
22
- js_source_files, js_test_files = ARGV.join(' ').split('--').map { |file_list| file_list.split(' ') }
23
- exit QUnited::Runner.run(js_source_files, js_test_files)
4
+ QUnited::Application.new.run
@@ -0,0 +1,108 @@
1
+ require 'optparse'
2
+ require 'ostruct'
3
+
4
+ module QUnited
5
+ class Application
6
+ def run
7
+ handle_exceptions do
8
+ handle_options
9
+ run_tests
10
+ end
11
+ end
12
+
13
+ def run_tests
14
+ js_source_files, js_test_files = ARGV.join(' ').split('--').map { |file_list| file_list.split(' ') }
15
+ exit QUnited::Runner.new(js_source_files, js_test_files, options).run
16
+ end
17
+
18
+ # Client options generally parsed from the command line
19
+ def options
20
+ @options ||= {}
21
+ end
22
+
23
+ # Parse and handle command line options
24
+ def handle_options
25
+ drivers = ::QUnited::Driver.constants.reject { |d| d == :Base }
26
+ valid_drivers_string = "Valid drivers include: #{drivers.map { |d| d.to_s }.join(', ')}"
27
+
28
+ args_empty = ARGV.empty?
29
+
30
+ # This is a bit of a hack, but OptionParser removes the -- that separates the source
31
+ # and test files and we need to put it back in the right place. Save the distance from
32
+ # the end to do this later.
33
+ double_dash_neg_index = ARGV.find_index('--') && (ARGV.find_index('--') - ARGV.size)
34
+
35
+ optparse = OptionParser.new do |opts|
36
+ opts.banner = <<-HELP_TEXT
37
+ Usage: qunited [OPTIONS] [JS_SOURCE_FILES...] -- [JS_TEST_FILES..]
38
+
39
+ Runs JavaScript unit tests with QUnit.
40
+
41
+ JS_SOURCE_FILES are the JavaScript files that you want to test. They will all be
42
+ loaded for running each test.
43
+
44
+ JS_TEST_FILES are files that contain the QUnit tests to run.
45
+
46
+ Options:
47
+ HELP_TEXT
48
+
49
+ opts.on('-d', '--driver [NAME]', 'Specify the driver to use in running the tests',
50
+ valid_drivers_string) do |name|
51
+ raise UsageError, 'Must specify a driver name with -d or --driver option' unless name
52
+ names_and_drivers = Hash[drivers.map { |d| d.to_s.downcase }.zip(drivers)]
53
+ driver = names_and_drivers[name.downcase]
54
+ raise UsageError, "Invalid driver specified: #{name}\n#{valid_drivers_string}" unless driver
55
+ options[:driver] = driver
56
+ end
57
+ opts.on_tail('-h', '--help', 'Show this message') do
58
+ puts opts
59
+ exit
60
+ end
61
+ opts.on_tail('--version', 'Print the QUnited version') do
62
+ puts ::QUnited::VERSION
63
+ exit
64
+ end
65
+
66
+ if args_empty
67
+ puts opts
68
+ exit 1
69
+ end
70
+ end.parse!
71
+
72
+ # Put the -- back in if we had one initially and it was removed
73
+ if double_dash_neg_index && !ARGV.include?('--')
74
+ ARGV.insert(double_dash_neg_index, '--')
75
+ end
76
+ end
77
+
78
+ private
79
+
80
+ def handle_exceptions
81
+ begin
82
+ yield
83
+ rescue SystemExit
84
+ exit
85
+ rescue UsageError => ex
86
+ $stderr.puts ex.message
87
+ exit 1
88
+ rescue OptionParser::InvalidOption => ex
89
+ $stderr.puts ex.message
90
+ exit 1
91
+ rescue Exception => ex
92
+ display_error_message ex
93
+ exit 1
94
+ end
95
+ end
96
+
97
+ def display_error_message(ex)
98
+ msg = <<MSG
99
+ QUnited has aborted! If this is unexpected, you may want to open an issue at
100
+ github.com/aaronroyer/qunited to get a possible bug fixed. If you do, please
101
+ include the debug information below.
102
+ MSG
103
+ $stderr.puts msg
104
+ $stderr.puts ex.message
105
+ $stderr.puts ex.backtrace
106
+ end
107
+ end
108
+ end
@@ -36,7 +36,7 @@ module QUnited
36
36
  end
37
37
  end
38
38
 
39
- @results = ::QUnited::Results.from_javascript_produced_yaml(IO.read(results_file))
39
+ @results = ::QUnited::Results.from_javascript_produced_json(IO.read(results_file))
40
40
  end
41
41
 
42
42
  private
@@ -95,7 +95,7 @@ page.open(tests_html_file, function(status) {
95
95
  }, function(){
96
96
  // Results should have been collected with code in qunited.js. Check that file
97
97
  // for more details. Grab the YAML it outputs and write it to the results file.
98
- var results = page.evaluate(function() { return QUnited.collectedTestResultsAsYaml(); });
98
+ var results = page.evaluate(function() { return QUnited.collectedTestResultsAsJson(); });
99
99
  fs.write(results_output_file, results, 'a');
100
100
  phantom.exit(0);
101
101
  });
@@ -11,7 +11,6 @@
11
11
  <ol id="qunit-tests"></ol>
12
12
  </body>
13
13
  <%= script_tag support_file_path('qunit.js') %>
14
- <%= script_tag support_file_path('yaml.js') %>
15
14
  <%= script_tag support_file_path('qunited.js') %>
16
15
 
17
16
  <script type="text/javascript" charset="utf-8">
@@ -44,7 +44,7 @@ module QUnited
44
44
  unless (err = stderr.read).strip.empty? then $stderr.puts(err) end
45
45
  end
46
46
 
47
- @results = ::QUnited::Results.from_javascript_produced_yaml(IO.read(results_file))
47
+ @results = ::QUnited::Results.from_javascript_produced_json(IO.read(results_file))
48
48
  end
49
49
  end
50
50
  end
@@ -8,7 +8,7 @@
8
8
  // test files.
9
9
  //
10
10
  // Example:
11
- // java -jar js.jar -opt -1 runner.js commonlibdir libdir outfile.yaml source.js -- test1.js test2.js
11
+ // java -jar js.jar -opt -1 runner.js commonlibdir libdir outfile.json source.js -- test1.js test2.js
12
12
  // ^ our args start here
13
13
 
14
14
  var QUnited = { sourceFiles: [], testFiles: [] };
@@ -20,7 +20,7 @@ var QUnited = { sourceFiles: [], testFiles: [] };
20
20
 
21
21
  load(libDir + '/env.rhino.js');
22
22
 
23
- ['qunit.js', 'yaml.js'].forEach(function(lib) {
23
+ ['qunit.js', 'qunited.js'].forEach(function(lib) {
24
24
  load(commonLibDir + '/' + lib);
25
25
  });
26
26
 
@@ -39,46 +39,7 @@ var QUnited = { sourceFiles: [], testFiles: [] };
39
39
  QUnit.config.autorun = true;
40
40
  QUnit.config.updateRate = 0;
41
41
 
42
- // Various state we'll need while running the tests
43
- QUnited.modulesMap = {};
44
- QUnited.currentTestFile = null; // Set when loading files, see below
45
- var currentModule, currentTest;
46
-
47
- ///// Listen for QUnit events during tests
48
-
49
- QUnit.testStart(function(data) {
50
- currentTest = {
51
- name: data.name,
52
- assertion_data: [], // Ruby-style, since we'll be reading it with Ruby
53
- start: new Date(),
54
- assertions: 0,
55
- file: QUnited.currentTestFile
56
- };
57
-
58
- var moduleName = data.module || "(no module)",
59
- module = QUnited.modulesMap[moduleName];
60
- if (!module) {
61
- module = {name: moduleName, tests: []};
62
- QUnited.modulesMap[moduleName] = module;
63
- }
64
- module.tests.push(currentTest);
65
- });
66
-
67
- QUnit.testDone(function(data) {
68
- currentTest.duration = ((new Date()).getTime() - currentTest.start.getTime()) / 1000;
69
- currentTest.failed = data.failed;
70
- currentTest.total = data.total;
71
- });
72
-
73
- /*
74
- * Called on every assertion AND whenever we have an expect(num) fail. You cannot tell this
75
- * apart from an assertion (even though you could make a good guess) with certainty so just
76
- * don't worry about it as it will only throw assertions count off on a failing test.
77
- */
78
- QUnit.log(function(data) {
79
- currentTest.assertions++;
80
- currentTest.assertion_data.push(data);
81
- });
42
+ QUnited.startCollectingTestResults();
82
43
 
83
44
  })(Array.prototype.slice.call(arguments, 0));
84
45
 
@@ -143,30 +104,7 @@ QUnited.testFiles.forEach(function(file) {
143
104
  });
144
105
 
145
106
  (function() {
146
- var modules = [];
147
-
148
- var ISODateString = function(d) {
149
- function pad(n) { return n < 10 ? '0' + n : n; }
150
- return d.getUTCFullYear() + '-' + pad(d.getUTCMonth() + 1)+'-' + pad(d.getUTCDate()) + 'T' +
151
- pad(d.getUTCHours()) + ':' + pad(d.getUTCMinutes()) + ':' + pad(d.getUTCSeconds()) + 'Z';
152
- }
153
-
154
- // Make a modules array for outputing results
155
- Object.keys(QUnited.modulesMap).forEach(function(key) {
156
- var mod = QUnited.modulesMap[key],
157
- tests = mod.tests;
158
- modules.push(mod);
159
- tests.forEach(function(test) {
160
- // YAML serializer doesn't seem to do dates; make them strings
161
- test.start = ISODateString(test.start);
162
- // Convert the duration to a string since the YAML serializer makes them all 0s otherwise
163
- test.duration = "" + test.duration;
164
- });
165
- });
166
-
167
-
168
- // Write all the results as YAML
169
107
  var writer = new java.io.PrintWriter(QUnited.outputFile);
170
- writer.write(YAML.encode(modules));
108
+ writer.write(QUnited.collectedTestResultsAsJson());
171
109
  writer.close();
172
110
  })();
@@ -53,24 +53,16 @@ QUnited.startCollectingTestResults = function() {
53
53
  });
54
54
  };
55
55
 
56
- QUnited.collectedTestResultsAsYaml = function() {
57
- var modules = [];
58
-
59
- // Make a modules array for outputing results
60
- Object.keys(QUnited.modulesMap).forEach(function(key) {
61
- var mod = QUnited.modulesMap[key],
62
- tests = mod.tests;
63
- modules.push(mod);
64
- tests.forEach(function(test) {
65
- // YAML serializer doesn't seem to do dates; make them strings
66
- test.start = QUnited.util.dateToString(test.start);
67
- // Convert the duration to a string since the YAML serializer makes them all 0s otherwise
68
- test.duration = "" + test.duration;
69
- });
56
+ /* Results as an Array of modules */
57
+ QUnited.collectedTestResults = function() {
58
+ return Object.keys(QUnited.modulesMap).map(function(key) {
59
+ return QUnited.modulesMap[key]
70
60
  });
61
+ };
71
62
 
72
- // Write all the results as YAML
73
- return YAML.encode(modules);
63
+ /* Module results as a JSON string */
64
+ QUnited.collectedTestResultsAsJson = function() {
65
+ return JSON.stringify(QUnited.collectedTestResults());
74
66
  };
75
67
 
76
68
  })();
@@ -13,9 +13,6 @@ module QUnited
13
13
  # order you will have to use source_files=(files_array).
14
14
  #
15
15
  # If an array of files is set with source_files=(files_array) then this will be ignored.
16
- #
17
- # default (unless source_files array is set):
18
- # 'app/assets/javascripts/**/*.js'
19
16
  attr_accessor :source_files_pattern
20
17
 
21
18
  # Array of JavaScript source files (and any dependencies). These will be loaded in order
@@ -25,14 +22,14 @@ module QUnited
25
22
  # Glob pattern to match QUnit test files.
26
23
  #
27
24
  # If an array of test files is set with test_files=(files) then this will be ignored.
28
- #
29
- # default:
30
- # 'test/javascripts/**/*.js'
31
25
  attr_accessor :test_files_pattern
32
26
 
33
27
  # Array of QUnit test files.
34
28
  attr_accessor :test_files
35
29
 
30
+ # The driver to use to run the QUnit tests.
31
+ attr_accessor :driver
32
+
36
33
  # Use verbose output. If this is true, the task will print the QUnited command to stdout.
37
34
  #
38
35
  # default:
@@ -41,6 +38,7 @@ module QUnited
41
38
 
42
39
  def initialize(*args)
43
40
  @name = args.shift || :qunited
41
+ @verbose = true
44
42
 
45
43
  yield self if block_given?
46
44
 
@@ -69,7 +67,9 @@ module QUnited
69
67
  private
70
68
 
71
69
  def command
72
- "qunited #{source_files_to_include.join(' ')} -- #{test_files_to_run.join(' ')}"
70
+ cmd = 'qunited'
71
+ cmd << " --driver #{driver}" if driver
72
+ cmd << " #{source_files_to_include.join(' ')} -- #{test_files_to_run.join(' ')}"
73
73
  end
74
74
 
75
75
  def source_files_to_include
@@ -81,8 +81,8 @@ module QUnited
81
81
  end
82
82
  end
83
83
 
84
- def self.from_javascript_produced_yaml(yaml)
85
- self.new clean_up_results(YAML.load(yaml))
84
+ def self.from_javascript_produced_json(json)
85
+ self.new clean_up_results(YAML.load(json))
86
86
  end
87
87
 
88
88
  def initialize(modules_results_array)
@@ -179,7 +179,6 @@ module QUnited
179
179
 
180
180
  def self.clean_up_test_results(test_results)
181
181
  test_results[:start] = DateTime.parse(test_results[:start])
182
- test_results[:duration] = Float(test_results[:duration])
183
182
  test_results[:assertion_data].map! { |data| symbolize_keys data }
184
183
  test_results
185
184
  end
@@ -2,22 +2,55 @@ module QUnited
2
2
  class Runner
3
3
 
4
4
  # The drivers in order of which to use first when not otherwise specified
5
- DRIVERS = [:PhantomJs, :Rhino].map { |driver| ::QUnited::Driver.const_get(driver) }.freeze
5
+ DRIVERS_PRIORITY = [:PhantomJs, :Rhino].freeze
6
6
 
7
- def self.run(js_source_files, js_test_files)
8
- driver_class = self.best_available_driver
9
- runner = driver_class.new(js_source_files, js_test_files)
7
+ attr_accessor :js_source_files, :js_test_files, :options
10
8
 
11
- puts "\n# Running JavaScript tests with #{runner.name}:\n\n"
9
+ def initialize(js_source_files, js_test_files, options={})
10
+ @js_source_files, @js_test_files, @options = js_source_files, js_test_files, options
11
+ end
12
+
13
+ def run
14
+ driver_class = resolve_driver_class
15
+ driver = driver_class.new(js_source_files, js_test_files)
16
+
17
+ puts "\n# Running JavaScript tests with #{driver.name}:\n\n"
12
18
 
13
- results = runner.run
19
+ results = driver.run
14
20
  puts results
15
21
  results.to_i
16
22
  end
17
23
 
24
+ def resolve_driver_class
25
+ if options[:driver]
26
+ begin
27
+ driver_class = get_driver(options[:driver])
28
+ rescue NameError
29
+ raise UsageError, "#{options[:driver].to_s} does not exist"
30
+ end
31
+
32
+ if !driver_class
33
+ raise UsageError, "#{driver_class} driver not found"
34
+ elsif !driver_class.available?
35
+ raise UsageError, "#{driver_class} driver specified, but not available"
36
+ end
37
+ driver_class
38
+ end
39
+
40
+ driver_class ||= best_available_driver
41
+ raise(UsageError, 'No driver available') unless driver_class
42
+ driver_class
43
+ end
44
+
45
+ def get_driver(klass)
46
+ if ::QUnited::Driver.constants.reject { |d| d == :Base }.include?(klass)
47
+ ::QUnited::Driver.const_get(klass)
48
+ end
49
+ end
50
+
18
51
  # Get the runner that we will be using to run the JavaScript tests.
19
- def self.best_available_driver
20
- DRIVERS.find { |driver| driver.available? }
52
+ def best_available_driver
53
+ DRIVERS_PRIORITY.map { |driver| get_driver(driver) }.find { |driver| driver.available? }
21
54
  end
22
55
  end
23
56
  end
@@ -1,3 +1,3 @@
1
1
  module QUnited
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
data/lib/qunited.rb CHANGED
@@ -2,3 +2,9 @@ require 'qunited/version'
2
2
  require 'qunited/results'
3
3
  require 'qunited/driver'
4
4
  require 'qunited/runner'
5
+ require 'qunited/application'
6
+
7
+ module QUnited
8
+ class UsageError < Exception
9
+ end
10
+ end
@@ -0,0 +1,60 @@
1
+ require File.expand_path('../../test_helper', __FILE__)
2
+
3
+ class AvailableDriver
4
+ def self.available?; true end
5
+ end
6
+
7
+ class NotAvailableDriver
8
+ def self.available?; false end
9
+ end
10
+
11
+ class TestRunner < MiniTest::Unit::TestCase
12
+ def test_raises_exception_with_nonexistent_driver
13
+ runner = QUnited::Runner.new(['source.js'], ['test.js'], { driver: :doesNotExist })
14
+ assert_raises(QUnited::UsageError) do
15
+ runner.resolve_driver_class
16
+ end
17
+ end
18
+
19
+ def test_specified_driver_can_be_used_if_available
20
+ runner = QUnited::Runner.new(['source.js'], ['test.js'], { driver: :AvailableDriver })
21
+
22
+ def runner.get_driver(klass)
23
+ if klass == :AvailableDriver
24
+ AvailableDriver
25
+ else
26
+ raise 'Only :AvailableDriver is used for this test'
27
+ end
28
+ end
29
+ runner.resolve_driver_class # Nothing raised
30
+ end
31
+
32
+ def test_raises_exception_when_not_available_driver_is_specified
33
+ runner = QUnited::Runner.new(['source.js'], ['test.js'], { driver: :NotAvailableDriver })
34
+
35
+ def runner.get_driver(klass)
36
+ if klass == :NotAvailableDriver
37
+ NotAvailableDriver
38
+ else
39
+ raise 'Only :NotAvailableDriver is used for this test'
40
+ end
41
+ end
42
+
43
+ assert_raises(QUnited::UsageError) do
44
+ runner.resolve_driver_class
45
+ end
46
+ end
47
+
48
+ def test_raises_exception_when_no_driver_specified_and_no_drivers_available
49
+ runner = QUnited::Runner.new(['source.js'], ['test.js'])
50
+
51
+ # Make every driver the NotAvailable driver
52
+ def runner.get_driver(klass)
53
+ NotAvailableDriver
54
+ end
55
+
56
+ assert_raises(QUnited::UsageError) do
57
+ runner.resolve_driver_class
58
+ end
59
+ end
60
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: qunited
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-07-06 00:00:00.000000000 Z
12
+ date: 2012-07-08 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: QUnited runs headless QUnit tests as part of your normal build
15
15
  email:
@@ -26,6 +26,7 @@ files:
26
26
  - Rakefile
27
27
  - bin/qunited
28
28
  - lib/qunited.rb
29
+ - lib/qunited/application.rb
29
30
  - lib/qunited/driver.rb
30
31
  - lib/qunited/driver/base.rb
31
32
  - lib/qunited/driver/phantomjs/phantomjs.rb
@@ -37,7 +38,6 @@ files:
37
38
  - lib/qunited/driver/rhino/support/runner.js
38
39
  - lib/qunited/driver/support/qunit.js
39
40
  - lib/qunited/driver/support/qunited.js
40
- - lib/qunited/driver/support/yaml.js
41
41
  - lib/qunited/rake_task.rb
42
42
  - lib/qunited/results.rb
43
43
  - lib/qunited/runner.rb
@@ -63,6 +63,7 @@ files:
63
63
  - test/unit/test_phantomjs_driver.rb
64
64
  - test/unit/test_results.rb
65
65
  - test/unit/test_rhino_driver.rb
66
+ - test/unit/test_runner.rb
66
67
  homepage: https://github.com/aaronroyer/qunited
67
68
  licenses: []
68
69
  post_install_message:
@@ -108,3 +109,4 @@ test_files:
108
109
  - test/unit/test_phantomjs_driver.rb
109
110
  - test/unit/test_results.rb
110
111
  - test/unit/test_rhino_driver.rb
112
+ - test/unit/test_runner.rb
@@ -1,22 +0,0 @@
1
- /*
2
- Copyright (c) 2010 Jeremy Faivre
3
-
4
- Permission is hereby granted, free of charge, to any person obtaining a copy
5
- of this software and associated documentation files (the "Software"), to deal
6
- in the Software without restriction, including without limitation the rights
7
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
- copies of the Software, and to permit persons to whom the Software is furnished
9
- to do so, subject to the following conditions:
10
-
11
- The above copyright notice and this permission notice shall be included in all
12
- copies or substantial portions of the Software.
13
-
14
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
- THE SOFTWARE.
21
- */
22
- var Yaml=function(){};Yaml.prototype={spec:"1.2",setSpecVersion:function(a){if(a!="1.1"&&a!="1.2"){throw new InvalidArgumentException("Version "+a+" of the YAML specifications is not supported")}this.spec=a},getSpecVersion:function(){return this.spec},loadFile:function(a,b){if(b==undefined){input=this.getFileContents(a);return this.load(input)}this.getFileContents(a,function(c){b(new Yaml().load(c))})},load:function(a){var c=new YamlParser();var b=null;try{b=c.parse(a)}catch(d){if(d.name!=undefined&&d.name.toString=="TypeError"){throw d}throw"Syntax error: "+d.message}return b},dump:function(b,a){if(a==undefined){a=2}yaml=new YamlDumper();return yaml.dump(b,a)},getXHR:function(){if(window.XMLHttpRequest){return new XMLHttpRequest()}if(window.ActiveXObject){var c=["Msxml2.XMLHTTP.6.0","Msxml2.XMLHTTP.3.0","Msxml2.XMLHTTP","Microsoft.XMLHTTP"];for(var a=0;a<4;a++){try{return new ActiveXObject(c[a])}catch(b){}}}return null},getFileContents:function(a,c){var b=this.getXHR();if(c==undefined){b.open("GET",a,false);b.send(null);if(b.status==200||b.status==0){return b.responseText}return null}b.onreadystatechange=function(){if(b.readyState==4){if(b.status==200||b.status==0){c(b.responseText)}else{c(null)}}};b.open("GET",a,true);b.send(null)}};var YAML={encode:function(a){return new Yaml().dump(a)},decode:function(a){return new Yaml().load(a)},load:function(a,b){return new Yaml().loadFile(a,b)}};if(typeof(InvalidArgumentException)=="undefined"){InvalidArgumentException=function(a){this.name="InvalidArgumentException";this.message=a}};var YamlInline=function(){};YamlInline.prototype={i:null,load:function(b){var a=null;b=this.trim(b);if(0==b.length){return""}switch(b.charAt(0)){case"[":a=this.parseSequence(b);break;case"{":a=this.parseMapping(b);break;default:a=this.parseScalar(b)}return a},dump:function(d){var b;var a;var c=new Yaml();if("1.1"==c.getSpecVersion()){b=["true","on","+","yes","y"];a=["false","off","-","no","n"]}else{b=["true"];a=["false"]}if(typeof(d)=="object"&&null!=d){return this.dumpObject(d)}if(undefined==d||null==d){return"null"}if(typeof(d)=="boolean"){return d?"true":"false"}if(/^\d+/.test(d)){return typeof(d)=="string"?"'"+d+"'":parseInt(d)}if(this.isNumeric(d)){return typeof(d)=="string"?"'"+d+"'":parseFloat(d)}if(typeof(d)=="number"){return d==Infinity?".Inf":(d==-Infinity?"-.Inf":(isNaN(d)?".NAN":d))}if((d+"").indexOf("\n")!=-1||(d+"").indexOf("\r")!=-1){return'"'+d.split('"').join('\\"').split("\n").join("\\n").split("\r").join("\\r")+'"'}if((/[\s\'"\:\{\}\[\],&\*\#\?]/.test(d))||(/^[-?|<>=!%@`]/.test(d))){return"'"+d.split("'").join("''")+"'"}if(""==d){return"''"}if(this.getTimestampRegex().test(d)){return"'"+d+"'"}if(this.inArray(d.toLowerCase(),b)){return"'"+d+"'"}if(this.inArray(d.toLowerCase(),a)){return"'"+d+"'"}if(this.inArray(d.toLowerCase(),["null","~"])){return"'"+d+"'"}return d},dumpObject:function(e){var d=this.getKeys(e);var b=null;var c;var a=d.length;if(e instanceof Array){b=[];for(c=0;c<a;c++){b.push(this.dump(e[d[c]]))}return"["+b.join(", ")+"]"}b=[];for(c=0;c<a;c++){b.push(this.dump(d[c])+": "+this.dump(e[d[c]]))}return"{ "+b.join(", ")+" }"},parseScalar:function(b,g,e,d,f){if(g==undefined){g=null}if(e==undefined){e=['"',"'"]}if(d==undefined){d=0}if(f==undefined){f=true}var a=null;var h=null;var c=null;if(this.inArray(b[d],e)){a=this.parseQuotedScalar(b,d);d=this.i}else{if(!g){a=(b+"").substring(d);d+=a.length;h=a.indexOf(" #");if(h!=-1){a=a.substr(0,h).replace(/\s+$/g,"")}}else{if(c=new RegExp("^(.+?)("+g.join("|")+")").exec((b+"").substring(d))){a=c[1];d+=a.length}else{throw new InvalidArgumentException("Malformed inline YAML string ("+b+").")}}a=f?this.evaluateScalar(a):a}this.i=d;return a},parseQuotedScalar:function(b,d){var c=null;if(!(c=new RegExp("^"+YamlInline.REGEX_QUOTED_STRING).exec((b+"").substring(d)))){throw new InvalidArgumentException("Malformed inline YAML string ("+(b+"").substring(d)+").")}var a=c[0].substr(1,c[0].length-2);if('"'==(b+"").charAt(d)){a=a.split('\\"').join('"').split("\\n").join("\n").split("\\r").join("\r")}else{a=a.split("''").join("'")}d+=c[0].length;this.i=d;return a},parseSequence:function(g,c){if(c==undefined){c=0}var b=[];var a=g.length;c+=1;while(c<a){switch(g.charAt(c)){case"[":b.push(this.parseSequence(g,c));c=this.i;break;case"{":b.push(this.parseMapping(g,c));c=this.i;break;case"]":this.i=c;return b;case",":case" ":break;default:isQuoted=this.inArray(g.charAt(c),['"',"'"]);var d=this.parseScalar(g,[",","]"],['"',"'"],c);c=this.i;if(!isQuoted&&(d+"").indexOf(": ")!=-1){try{d=this.parseMapping("{"+d+"}")}catch(f){if(!(f instanceof InvalidArgumentException)){throw f}}}b.push(d);c--}c++}throw new InvalidArgumentException("Malformed inline YAML string "+g)},parseMapping:function(d,f){if(f==undefined){f=0}var c={};var a=d.length;f+=1;var b=false;var g=false;while(f<a){g=false;switch(d.charAt(f)){case" ":case",":f++;g=true;break;case"}":this.i=f;return c}if(g){continue}var e=this.parseScalar(d,[":"," "],['"',"'"],f,false);f=this.i;b=false;while(f<a){switch(d.charAt(f)){case"[":c[e]=this.parseSequence(d,f);f=this.i;b=true;break;case"{":c[e]=this.parseMapping(d,f);f=this.i;b=true;break;case":":case" ":break;default:c[e]=this.parseScalar(d,[",","}"],['"',"'"],f);f=this.i;b=true;f--}++f;if(b){g=true;break}}if(g){continue}}throw new InvalidArgumentException("Malformed inline YAML string "+d)},evaluateScalar:function(b){b=this.trim(b);var e;var d;var f=new Yaml();if("1.1"==f.getSpecVersion()){e=["true","on","+","yes","y"];d=["false","off","-","no","n"]}else{e=["true"];d=["false"]}var c=null;var a=null;if(("null"==b.toLowerCase())||(""==b)||("~"==b)){return null}if((b+"").indexOf("!str")!=-1){return(""+b).substring(5)}if((b+"").indexOf("! ")!=-1){return parseInt(this.parseScalar((b+"").substring(2)))}if(/^\d+/.test(b)){c=b;a=parseInt(b);return"0"==b.charAt(0)?this.octdec(b):((""+c==""+a)?a:c)}if(this.inArray(b.toLowerCase(),e)){return true}if(this.inArray(b.toLowerCase(),d)){return false}if(this.isNumeric(b)){return"0x"==(b+"").substr(0,2)?hexdec($scalar):floatval($scalar)}if(b.toLowerCase()==".inf"){return Infinity}if(b.toLowerCase()==".nan"){return NaN}if(b.toLowerCase()=="-.inf"){return -Infinity}if(/^(-|\+)?[0-9,]+(\.[0-9]+)?$/.test(b)){return parseFloat(b.split(",").join(""))}if(this.getTimestampRegex().test(b)){return this.strtodate(b)}return""+b},getTimestampRegex:function(){return new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)(?:(?:[Tt]|[ \t]+)([0-9][0-9]?):([0-9][0-9]):([0-9][0-9])(?:.([0-9]*))?(?:[ \t]*(Z|([-+])([0-9][0-9]?)(?::([0-9][0-9]))?))?)?$","gi")},trim:function(a){return(a+"").replace(/^\s+/,"").replace(/\s+$/,"")},isNumeric:function(a){return(a-0)==a&&a.length>0&&a.replace(/\s+/g,"")!=""},inArray:function(c,d){var b;var a=d.length;for(b=0;b<a;b++){if(c==d[b]){return true}}return false},getKeys:function(c){var b=[];for(var a in c){if(c.hasOwnProperty(a)){b.push(a)}}return b},octdec:function(a){return parseInt((a+"").replace(/[^0-7]/gi,""),8)},hexdec:function(a){a=this.trim(a);if((a+"").substr(0,2)=="0x"){a=(a+"").substring(2)}return parseInt((a+"").replace(/[^a-f0-9]/gi,""),16)},strtodate:function(a){var b=new Date();b.setTime(this.strtotime(a,new Date().getTime()));return b},strtotime:function(o,t){var q,p,i,m="",s="";m=o;m=m.replace(/\s{2,}|^\s|\s$/g," ");m=m.replace(/[\t\r\n]/g,"");if(m=="now"){return(new Date()).getTime()/1000}else{if(!isNaN(s=Date.parse(m))){return(s/1000)}else{if(t){t=new Date(t*1000)}else{t=new Date()}}}m=m.toLowerCase();var r={day:{sun:0,mon:1,tue:2,wed:3,thu:4,fri:5,sat:6},mon:{jan:0,feb:1,mar:2,apr:3,may:4,jun:5,jul:6,aug:7,sep:8,oct:9,nov:10,dec:11}};var v=this.strtotime;var u=function(a){var c=(a[2]&&a[2]=="ago");var d=(d=a[0]=="last"?-1:1)*(c?-1:1);switch(a[0]){case"last":case"next":switch(a[1].substring(0,3)){case"yea":t.setFullYear(t.getFullYear()+d);break;case"mon":t.setMonth(t.getMonth()+d);break;case"wee":t.setDate(t.getDate()+(d*7));break;case"day":t.setDate(t.getDate()+d);break;case"hou":t.setHours(t.getHours()+d);break;case"min":t.setMinutes(t.getMinutes()+d);break;case"sec":t.setSeconds(t.getSeconds()+d);break;default:var e;if(typeof(e=r.day[a[1].substring(0,3)])!="undefined"){var b=e-t.getDay();if(b==0){b=7*d}else{if(b>0){if(a[0]=="last"){b-=7}}else{if(a[0]=="next"){b+=7}}}t.setDate(t.getDate()+b)}}break;default:if(/\d+/.test(a[0])){d*=parseInt(a[0],10);switch(a[1].substring(0,3)){case"yea":t.setFullYear(t.getFullYear()+d);break;case"mon":t.setMonth(t.getMonth()+d);break;case"wee":t.setDate(t.getDate()+(d*7));break;case"day":t.setDate(t.getDate()+d);break;case"hou":t.setHours(t.getHours()+d);break;case"min":t.setMinutes(t.getMinutes()+d);break;case"sec":t.setSeconds(t.getSeconds()+d);break}}else{return false}break}return true};p=m.match(/^(\d{2,4}-\d{2}-\d{2})(?:\s(\d{1,2}:\d{2}(:\d{2})?)?(?:\.(\d+))?)?$/);if(p!=null){if(!p[2]){p[2]="00:00:00"}else{if(!p[3]){p[2]+=":00"}}i=p[1].split(/-/g);for(q in r.mon){if(r.mon[q]==i[1]-1){i[1]=q}}i[0]=parseInt(i[0],10);i[0]=(i[0]>=0&&i[0]<=69)?"20"+(i[0]<10?"0"+i[0]:i[0]+""):(i[0]>=70&&i[0]<=99)?"19"+i[0]:i[0]+"";return parseInt(v(i[2]+" "+i[1]+" "+i[0]+" "+p[2])+(p[4]?p[4]/1000:""),10)}var n="([+-]?\\d+\\s(years?|months?|weeks?|days?|hours?|min|minutes?|sec|seconds?|sun\\.?|sunday|mon\\.?|monday|tue\\.?|tuesday|wed\\.?|wednesday|thu\\.?|thursday|fri\\.?|friday|sat\\.?|saturday)|(last|next)\\s(years?|months?|weeks?|days?|hours?|min|minutes?|sec|seconds?|sun\\.?|sunday|mon\\.?|monday|tue\\.?|tuesday|wed\\.?|wednesday|thu\\.?|thursday|fri\\.?|friday|sat\\.?|saturday))(\\sago)?";p=m.match(new RegExp(n,"gi"));if(p==null){return false}for(q=0;q<p.length;q++){if(!u(p[q].split(" "))){return false}}return(t.getTime()/1000)}};YamlInline.REGEX_QUOTED_STRING="(?:\"(?:[^\"\\\\]*(?:\\\\.[^\"\\\\]*)*)\"|'(?:[^']*(?:''[^']*)*)')";var YamlParser=function(a){this.offset=this.isDefined(a)?a:0};YamlParser.prototype={offset:0,lines:[],currentLineNb:-1,currentLine:"",refs:{},parse:function(m){this.currentLineNb=-1;this.currentLine="";this.lines=this.cleanup(m).split("\n");var u=null;while(this.moveToNextLine()){if(this.isCurrentLineEmpty()){continue}if(/^\t+/.test(this.currentLine)){throw new InvalidArgumentException("A YAML file cannot contain tabs as indentation at line "+(this.getRealCurrentLineNb()+1)+" ("+this.currentLine+")")}var j=false;var r=false;var q=false;var b=null;var a=null;var t=null;var d=null;var e=null;var v=null;var h=null;var p=null;var f=null;if(b=/^\-((\s+)(.+?))?\s*$/.exec(this.currentLine)){if(!this.isDefined(u)){u=[]}if(!(u instanceof Array)){throw new InvalidArgumentException("Non array entry at line "+(this.getRealCurrentLineNb()+1)+".")}b={leadspaces:b[2],value:b[3]};if(this.isDefined(b.value)&&(a=/^&([^ ]+) *(.*)/.exec(b.value))){a={ref:a[1],value:a[2]};j=a.ref;b.value=a.value}if(!this.isDefined(b.value)||""==b.value.split(" ").join("")||this.trim(b.value).charAt(0)=="#"){t=this.getRealCurrentLineNb()+1;d=new YamlParser(t);d.refs=this.refs;u.push(d.parse(this.getNextEmbedBlock()));this.refs=d.refs}else{if(this.isDefined(b.leadspaces)&&" "==b.leadspaces&&(a=new RegExp("^("+YamlInline.REGEX_QUOTED_STRING+"|[^ '\"{].*?) *:(\\s+(.+?))?\\s*$").exec(b.value))){a={key:a[1],value:a[3]};t=this.getRealCurrentLineNb();d=new YamlParser(t);d.refs=this.refs;e=b.value;if(!this.isNextLineIndented()){e+="\n"+this.getNextEmbedBlock(this.getCurrentLineIndentation()+2)}u.push(d.parse(e));this.refs=d.refs}else{u.push(this.parseValue(b.value))}}}else{if(b=new RegExp("^("+YamlInline.REGEX_QUOTED_STRING+"|[^ '\"].*?) *:(\\s+(.+?))?\\s*$").exec(this.currentLine)){if(!this.isDefined(u)){u={}}if(u instanceof Array){throw new InvalidArgumentException("Non mapped entry at line "+(this.getRealCurrentLineNb()+1)+".")}b={key:b[1],value:b[3]};v=(new YamlInline()).parseScalar(b.key);if("<<"==v){if(this.isDefined(b.value)&&"*"==(b.value+"").charAt(0)){r=b.value.substring(1)}else{if(this.isDefined(b.value)&&b.value!=""){m=b.value}else{m=this.getNextEmbedBlock()}t=this.getRealCurrentLineNb()+1;d=new YamlParser(t);d.refs=this.refs;h=d.parse(m);this.refs=d.refs;var s=[];if(!this.isObject(h)){throw new InvalidArgumentException("YAML merge keys used with a scalar value instead of an array at line "+(this.getRealCurrentLineNb()+1)+" ("+this.currentLine+")")}else{if(this.isDefined(h[0])){f=this.reverseArray(h);p=f.length;for(var o=0;o<p;o++){var l=f[o];if(!this.isObject(f[o])){throw new InvalidArgumentException("Merge items must be arrays at line "+(this.getRealCurrentLineNb()+1)+" ("+f[o]+").")}s=this.mergeObject(f[o],s)}}else{s=this.mergeObject(s,h)}}q=s}}else{if(this.isDefined(b.value)&&(a=/^&([^ ]+) *(.*)/.exec(b.value))){a={ref:a[1],value:a[2]};j=a.ref;b.value=a.value}}if(q){u=q}else{if(!this.isDefined(b.value)||""==b.value.split(" ").join("")||this.trim(b.value).charAt(0)=="#"){if(this.isNextLineIndented()){u[v]=null}else{t=this.getRealCurrentLineNb()+1;d=new YamlParser(t);d.refs=this.refs;u[v]=d.parse(this.getNextEmbedBlock());this.refs=d.refs}}else{if(r){u=this.refs[r]}else{u[v]=this.parseValue(b.value)}}}}else{if(2==this.lines.length&&this.isEmpty(this.lines[1])){m=(new YamlInline()).load(this.lines[0]);if(this.isObject(m)){first=m[0];if("*"==(first+"").substr(0,1)){u=[];p=m.length;for(var o=0;o<p;o++){u.push(this.refs[m[o].substring(1)])}m=u}}return m}throw new InvalidArgumentException('"'+this.currentLine+'" at line '+(this.getRealCurrentLineNb()+1))}}if(j){if(u instanceof Array){this.refs[j]=u[u.length-1]}else{var g=null;for(var n in u){if(u.hasOwnProperty(n)){g=n}}this.refs[j]=u[n]}}}return this.isEmpty(u)?null:u},getRealCurrentLineNb:function(){return this.currentLineNb+this.offset},getCurrentLineIndentation:function(){return this.currentLine.length-this.currentLine.replace(/^ +/g,"").length},getNextEmbedBlock:function(d){this.moveToNextLine();var b=null;var a=null;if(!this.isDefined(d)){b=this.getCurrentLineIndentation();if(!this.isCurrentLineEmpty()&&0==b){throw new InvalidArgumentException("A Indentation problem at line "+(this.getRealCurrentLineNb()+1)+" ("+this.currentLine+")")}}else{b=d}var e=[this.currentLine.substring(b)];while(this.moveToNextLine()){if(this.isCurrentLineEmpty()){if(this.isCurrentLineBlank()){e.push(this.currentLine.substring(b))}continue}a=this.getCurrentLineIndentation();var c;if(c=/^( *)$/.exec(this.currentLine)){e.push(c[1])}else{if(a>=b){e.push(this.currentLine.substring(b))}else{if(0==a){this.moveToPreviousLine();break}else{throw new InvalidArgumentException("B Indentation problem at line "+(this.getRealCurrentLineNb()+1)+" ("+this.currentLine+")")}}}}return e.join("\n")},moveToNextLine:function(){if(this.currentLineNb>=this.lines.length-1){return false}this.currentLineNb++;this.currentLine=this.lines[this.currentLineNb];return true},moveToPreviousLine:function(){this.currentLineNb--;this.currentLine=this.lines[this.currentLineNb]},parseValue:function(c){if("*"==(c+"").charAt(0)){if(this.trim(c).charAt(0)=="#"){c=(c+"").substr(1,c.indexOf("#")-2)}else{c=(c+"").substring(1)}if(this.refs[c]==undefined){throw new InvalidArgumentException('Reference "'+c+'" does not exist ('+this.currentLine+").")}return this.refs[c]}var b=null;if(b=/^(\||>)(\+|\-|\d+|\+\d+|\-\d+|\d+\+|\d+\-)?( +#.*)?$/.exec(c)){b={separator:b[1],modifiers:b[2],comments:b[3]};var a=this.isDefined(b.modifiers)?b.modifiers:"";return this.parseFoldedScalar(b.separator,a.replace(/\d+/g,""),Math.abs(parseInt(a)))}else{return(new YamlInline()).load(c)}},parseFoldedScalar:function(c,h,f){if(h==undefined){h=""}if(f==undefined){f=0}c="|"==c?"\n":" ";var j="";var g=null;var b=this.moveToNextLine();while(b&&this.isCurrentLineBlank()){j+="\n";b=this.moveToNextLine()}if(!b){return""}var d=null;if(!(d=new RegExp("^("+(f?this.strRepeat(" ",f):" +")+")(.*)$").exec(this.currentLine))){this.moveToPreviousLine();return""}d={indent:d[1],text:d[2]};var a=d.indent;var e=0;j+=d.text+c;while(this.currentLineNb+1<this.lines.length){this.moveToNextLine();if(d=new RegExp("^( {"+a.length+",})(.+)$").exec(this.currentLine)){d={indent:d[1],text:d[2]};if(" "==c&&e!=d.indent){j=j.substr(0,j.length-1)+"\n"}e=d.indent;g=d.indent.length-a.length;j+=this.strRepeat(" ",g)+d.text+(g!=0?"\n":c)}else{if(d=/^( *)$/.exec(this.currentLine)){j+=d[1].replace(new RegExp("^ {1,"+a.length+"}","g"),"",d[1])+"\n"}else{this.moveToPreviousLine();break}}}if(" "==c){j=j.replace(/ (\n*)$/g,"\n$1")}switch(h){case"":j=j.replace(/\n+$/g,"\n");break;case"+":break;case"-":j=j.replace(/\n+$/g,"");break}return j},isNextLineIndented:function(){var b=this.getCurrentLineIndentation();var c=this.moveToNextLine();while(c&&this.isCurrentLineEmpty()){c=this.moveToNextLine()}if(false==c){return false}var a=false;if(this.getCurrentLineIndentation()<=b){a=true}this.moveToPreviousLine();return a},isCurrentLineEmpty:function(){return this.isCurrentLineBlank()||this.isCurrentLineComment()},isCurrentLineBlank:function(){return""==this.currentLine.split(" ").join("")},isCurrentLineComment:function(){var a=this.currentLine.replace(/^ +/g,"");return a.charAt(0)=="#"},cleanup:function(c){c=c.split("\r\n").join("\n").split("\r").join("\n");if(!/\n$/.test(c)){c+="\n"}var b=0;var a=/^\%YAML[: ][\d\.]+.*\n/;while(a.test(c)){c=c.replace(a,"");b++}this.offset+=b;a=/^(#.*?\n)+/;if(a.test(c)){trimmedValue=c.replace(a,"");this.offset+=this.subStrCount(c,"\n")-this.subStrCount(trimmedValue,"\n");c=trimmedValue}a=/^\-\-\-.*?\n/;if(a.test(c)){trimmedValue=c.replace(a,"");this.offset+=this.subStrCount(c,"\n")-this.subStrCount(trimmedValue,"\n");c=trimmedValue;c=c.replace(/\.\.\.\s*$/g,"")}return c},isObject:function(a){return typeof(a)=="object"&&this.isDefined(a)},isEmpty:function(a){return a==undefined||a==null||a==""||a==0||a=="0"||a==false},isDefined:function(a){return a!=undefined&&a!=null},reverseArray:function(c){var b=[];var a=c.length;for(var d=a-1;d>=0;d--){b.push(c[d])}return b},merge:function(e,d){var f={};for(i in e){if(/^\d+$/.test(i)){f.push(e)}else{f[i]=e[i]}}for(i in d){if(/^\d+$/.test(i)){f.push(d)}else{f[i]=d[i]}}return f},strRepeat:function(d,c){var b;var a="";for(b=0;b<c;b++){a+=d}return d},subStrCount:function(d,b,j,f){var h=0;d=""+d;b=""+b;if(j!=undefined){d=d.substr(j)}if(f!=undefined){d=d.substr(0,f)}var a=d.length;var g=b.length;for(var e=0;e<a;e++){if(b==d.substr(e,g)){h++}}return h},trim:function(a){return(a+"").replace(/^\s+/,"").replace(/\s+$/,"")}};YamlDumper=function(){};YamlDumper.prototype={dump:function(g,f,c){if(f==undefined){f=0}if(c==undefined){c=0}var b="";var e=c?this.strRepeat(" ",c):"";var i;if(f<=0||!this.isObject(g)||this.isEmpty(g)){i=new YamlInline();b+=e+i.dump(g)}else{var d=!this.arrayEquals(this.getKeys(g),this.range(0,g.length-1));var a;for(var h in g){if(g.hasOwnProperty(h)){a=f-1<=0||!this.isObject(g[h])||this.isEmpty(g[h]);if(d){i=new YamlInline()}b+=e+""+(d?i.dump(h)+":":"-")+""+(a?" ":"\n")+""+this.dump(g[h],f-1,(a?0:c+2))+""+(a?"\n":"")}}}return b},strRepeat:function(d,c){var b;var a="";for(b=0;b<c;b++){a+=d}return d},isObject:function(a){return typeof(a)=="object"&&this.isDefined(a)},isEmpty:function(a){return a==undefined||a==null||a==""||a==0||a=="0"||a==false},isDefined:function(a){return a!=undefined&&a!=null},getKeys:function(c){var b=[];for(var a in c){if(c.hasOwnProperty(a)){b.push(a)}}return b},range:function(d,a){if(d>a){return[]}var b=[];for(var c=d;c<=a;c++){b.push(c)}return b},arrayEquals:function(e,d){if(e.length!=d.length){return false}var c=e.length;for(var f=0;f<c;f++){if(e[f]!=d[f]){return false}}return true}};