sproutcore 0.9.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/History.txt +4 -0
- data/License.txt +20 -0
- data/Manifest.txt +269 -0
- data/README.txt +67 -0
- data/Rakefile +4 -0
- data/app_generators/sproutcore/USAGE +5 -0
- data/app_generators/sproutcore/sproutcore_generator.rb +66 -0
- data/app_generators/sproutcore/templates/README +77 -0
- data/app_generators/sproutcore/templates/environment.yml +4 -0
- data/bin/sc-build +145 -0
- data/bin/sc-gen +24 -0
- data/bin/sc-server +63 -0
- data/bin/sproutcore +21 -0
- data/clients/sc_docs/controllers/docs.js +118 -0
- data/clients/sc_docs/core.js +19 -0
- data/clients/sc_docs/english.lproj/body.css +159 -0
- data/clients/sc_docs/english.lproj/body.rhtml +33 -0
- data/clients/sc_docs/english.lproj/controls.css +0 -0
- data/clients/sc_docs/english.lproj/icons/small/next.png +0 -0
- data/clients/sc_docs/english.lproj/icons/small/reset.png +0 -0
- data/clients/sc_docs/english.lproj/images/gradients.png +0 -0
- data/clients/sc_docs/english.lproj/images/indicator.gif +0 -0
- data/clients/sc_docs/english.lproj/images/toolbar.png +0 -0
- data/clients/sc_docs/english.lproj/no_docs.rhtml +7 -0
- data/clients/sc_docs/english.lproj/strings.js +14 -0
- data/clients/sc_docs/english.lproj/warning.rhtml +6 -0
- data/clients/sc_docs/fixtures/doc.js +11 -0
- data/clients/sc_docs/main.js +21 -0
- data/clients/sc_docs/models/doc.js +9 -0
- data/clients/sc_docs/tests/controllers/docs.rhtml +21 -0
- data/clients/sc_docs/tests/models/doc.rhtml +21 -0
- data/clients/sc_docs/tests/views/doc_frame.rhtml +21 -0
- data/clients/sc_docs/tests/views/doc_label_view.rhtml +21 -0
- data/clients/sc_docs/views/doc_frame.js +33 -0
- data/clients/sc_docs/views/doc_label.js +20 -0
- data/clients/sc_test_runner/controllers/runner.js +175 -0
- data/clients/sc_test_runner/core.js +19 -0
- data/clients/sc_test_runner/english.lproj/body.css +151 -0
- data/clients/sc_test_runner/english.lproj/body.rhtml +35 -0
- data/clients/sc_test_runner/english.lproj/controls.css +0 -0
- data/clients/sc_test_runner/english.lproj/icons/small/next.png +0 -0
- data/clients/sc_test_runner/english.lproj/icons/small/reset.png +0 -0
- data/clients/sc_test_runner/english.lproj/images/gradients.png +0 -0
- data/clients/sc_test_runner/english.lproj/images/indicator.gif +0 -0
- data/clients/sc_test_runner/english.lproj/images/toolbar.png +0 -0
- data/clients/sc_test_runner/english.lproj/no_tests.rhtml +6 -0
- data/clients/sc_test_runner/english.lproj/strings.js +14 -0
- data/clients/sc_test_runner/english.lproj/warning.rhtml +6 -0
- data/clients/sc_test_runner/fixtures/test.js +12 -0
- data/clients/sc_test_runner/main.js +26 -0
- data/clients/sc_test_runner/models/test.js +11 -0
- data/clients/sc_test_runner/views/runner_frame.js +72 -0
- data/clients/sc_test_runner/views/test_label.js +20 -0
- data/config/hoe.rb +70 -0
- data/config/requirements.rb +17 -0
- data/environment.yml +9 -0
- data/frameworks/prototype/prototype.js +4186 -0
- data/frameworks/sproutcore/Core.js +378 -0
- data/frameworks/sproutcore/README +3 -0
- data/frameworks/sproutcore/controllers/array.js +236 -0
- data/frameworks/sproutcore/controllers/collection.js +305 -0
- data/frameworks/sproutcore/controllers/controller.js +323 -0
- data/frameworks/sproutcore/controllers/object.js +372 -0
- data/frameworks/sproutcore/drag/drag.js +549 -0
- data/frameworks/sproutcore/drag/drag_data_source.js +32 -0
- data/frameworks/sproutcore/drag/drag_source.js +64 -0
- data/frameworks/sproutcore/drag/drop_target.js +153 -0
- data/frameworks/sproutcore/english.lproj/blank.gif +0 -0
- data/frameworks/sproutcore/english.lproj/buttons.css +589 -0
- data/frameworks/sproutcore/english.lproj/buttons.png +0 -0
- data/frameworks/sproutcore/english.lproj/inline_text_editor.css +21 -0
- data/frameworks/sproutcore/english.lproj/menu.css +121 -0
- data/frameworks/sproutcore/english.lproj/panels/background-fat.jpg +0 -0
- data/frameworks/sproutcore/english.lproj/panels/background-thin.jpg +0 -0
- data/frameworks/sproutcore/english.lproj/panels/bottom-edge.png +0 -0
- data/frameworks/sproutcore/english.lproj/panels/bottom-left-corner.png +0 -0
- data/frameworks/sproutcore/english.lproj/panels/bottom-right-corner.png +0 -0
- data/frameworks/sproutcore/english.lproj/panels/left-edge.png +0 -0
- data/frameworks/sproutcore/english.lproj/panels/overlay.png +0 -0
- data/frameworks/sproutcore/english.lproj/panels/right-edge.png +0 -0
- data/frameworks/sproutcore/english.lproj/panels/top-edge.png +0 -0
- data/frameworks/sproutcore/english.lproj/panels/top-left-corner.png +0 -0
- data/frameworks/sproutcore/english.lproj/panels/top-right-corner.png +0 -0
- data/frameworks/sproutcore/english.lproj/panes.css +155 -0
- data/frameworks/sproutcore/english.lproj/picker.css +22 -0
- data/frameworks/sproutcore/english.lproj/strings.js +15 -0
- data/frameworks/sproutcore/english.lproj/tab.css +23 -0
- data/frameworks/sproutcore/english.lproj/tests.css +67 -0
- data/frameworks/sproutcore/english.lproj/theme.css +77 -0
- data/frameworks/sproutcore/foundation/animator.js +670 -0
- data/frameworks/sproutcore/foundation/application.js +199 -0
- data/frameworks/sproutcore/foundation/array.js +348 -0
- data/frameworks/sproutcore/foundation/benchmark.js +211 -0
- data/frameworks/sproutcore/foundation/binding.js +384 -0
- data/frameworks/sproutcore/foundation/date.js +357 -0
- data/frameworks/sproutcore/foundation/error.js +39 -0
- data/frameworks/sproutcore/foundation/input_manager.js +153 -0
- data/frameworks/sproutcore/foundation/json.js +296 -0
- data/frameworks/sproutcore/foundation/mock.js +42 -0
- data/frameworks/sproutcore/foundation/node_descriptor.js +56 -0
- data/frameworks/sproutcore/foundation/object.js +777 -0
- data/frameworks/sproutcore/foundation/observable.js +451 -0
- data/frameworks/sproutcore/foundation/page.js +63 -0
- data/frameworks/sproutcore/foundation/path_module.js +413 -0
- data/frameworks/sproutcore/foundation/responder.js +310 -0
- data/frameworks/sproutcore/foundation/routes.js +371 -0
- data/frameworks/sproutcore/foundation/run_loop.js +21 -0
- data/frameworks/sproutcore/foundation/server.js +491 -0
- data/frameworks/sproutcore/foundation/set.js +96 -0
- data/frameworks/sproutcore/foundation/string.js +149 -0
- data/frameworks/sproutcore/foundation/undo_manager.js +186 -0
- data/frameworks/sproutcore/foundation/unittest.js +622 -0
- data/frameworks/sproutcore/foundation/utils.js +61 -0
- data/frameworks/sproutcore/globals/panels.js +182 -0
- data/frameworks/sproutcore/globals/popups.js +60 -0
- data/frameworks/sproutcore/globals/window.js +381 -0
- data/frameworks/sproutcore/lib/index.rhtml +66 -0
- data/frameworks/sproutcore/models/collection.js +395 -0
- data/frameworks/sproutcore/models/record.js +622 -0
- data/frameworks/sproutcore/models/store.js +295 -0
- data/frameworks/sproutcore/panes/dialog.js +16 -0
- data/frameworks/sproutcore/panes/manager.js +164 -0
- data/frameworks/sproutcore/panes/menu.js +45 -0
- data/frameworks/sproutcore/panes/overlay.js +231 -0
- data/frameworks/sproutcore/panes/pane.js +90 -0
- data/frameworks/sproutcore/panes/panel.js +19 -0
- data/frameworks/sproutcore/panes/picker.js +45 -0
- data/frameworks/sproutcore/tests/controllers/array.rhtml +86 -0
- data/frameworks/sproutcore/tests/controllers/controller.rhtml +273 -0
- data/frameworks/sproutcore/tests/controllers/object.rhtml +327 -0
- data/frameworks/sproutcore/tests/foundation/application.rhtml +125 -0
- data/frameworks/sproutcore/tests/foundation/array.rhtml +221 -0
- data/frameworks/sproutcore/tests/foundation/object.rhtml +69 -0
- data/frameworks/sproutcore/tests/globals/window.rhtml +45 -0
- data/frameworks/sproutcore/tests/panes/pane.rhtml +88 -0
- data/frameworks/sproutcore/tests/views/collection.rhtml +137 -0
- data/frameworks/sproutcore/tests/views/popup_button.rhtml +115 -0
- data/frameworks/sproutcore/tests/views/text_field.rhtml +37 -0
- data/frameworks/sproutcore/validators/credit_card.js +92 -0
- data/frameworks/sproutcore/validators/date.js +36 -0
- data/frameworks/sproutcore/validators/email.js +29 -0
- data/frameworks/sproutcore/validators/not_empty.js +24 -0
- data/frameworks/sproutcore/validators/number.js +55 -0
- data/frameworks/sproutcore/validators/password.js +78 -0
- data/frameworks/sproutcore/validators/validator.js +304 -0
- data/frameworks/sproutcore/views/button.js +425 -0
- data/frameworks/sproutcore/views/checkbox_field.js +30 -0
- data/frameworks/sproutcore/views/collection.js +1521 -0
- data/frameworks/sproutcore/views/container.js +62 -0
- data/frameworks/sproutcore/views/error_explanation.js +45 -0
- data/frameworks/sproutcore/views/field.js +214 -0
- data/frameworks/sproutcore/views/filter_button.js +29 -0
- data/frameworks/sproutcore/views/form.js +591 -0
- data/frameworks/sproutcore/views/image.js +141 -0
- data/frameworks/sproutcore/views/inline_text_editor.js +96 -0
- data/frameworks/sproutcore/views/label.js +176 -0
- data/frameworks/sproutcore/views/menu_item.js +90 -0
- data/frameworks/sproutcore/views/pagination.js +54 -0
- data/frameworks/sproutcore/views/popup_button.js +86 -0
- data/frameworks/sproutcore/views/popup_menu.js +137 -0
- data/frameworks/sproutcore/views/progress.js +100 -0
- data/frameworks/sproutcore/views/radio_field.js +107 -0
- data/frameworks/sproutcore/views/radio_group.js +48 -0
- data/frameworks/sproutcore/views/segmented.js +80 -0
- data/frameworks/sproutcore/views/select_field.js +272 -0
- data/frameworks/sproutcore/views/spinner.js +11 -0
- data/frameworks/sproutcore/views/tab.js +126 -0
- data/frameworks/sproutcore/views/text_field.js +179 -0
- data/frameworks/sproutcore/views/textarea_field.js +14 -0
- data/frameworks/sproutcore/views/toolbar.js +29 -0
- data/frameworks/sproutcore/views/view.js +1389 -0
- data/frameworks/sproutcore/views/workspace.js +170 -0
- data/generators/client/README +3 -0
- data/generators/client/USAGE +12 -0
- data/generators/client/client_generator.rb +53 -0
- data/generators/client/templates/core.js +19 -0
- data/generators/client/templates/english.lproj/body.css +0 -0
- data/generators/client/templates/english.lproj/body.rhtml +3 -0
- data/generators/client/templates/english.lproj/controls.css +0 -0
- data/generators/client/templates/english.lproj/strings.js +14 -0
- data/generators/client/templates/main.js +37 -0
- data/generators/controller/USAGE +16 -0
- data/generators/controller/controller_generator.rb +51 -0
- data/generators/controller/templates/controller.js +21 -0
- data/generators/controller/templates/test.rhtml +21 -0
- data/generators/framework/README +7 -0
- data/generators/framework/USAGE +12 -0
- data/generators/framework/framework_generator.rb +53 -0
- data/generators/framework/templates/core.js +20 -0
- data/generators/framework/templates/english.lproj/body.css +0 -0
- data/generators/framework/templates/english.lproj/body.rhtml +3 -0
- data/generators/framework/templates/english.lproj/controls.css +0 -0
- data/generators/framework/templates/english.lproj/strings.js +14 -0
- data/generators/language/USAGE +16 -0
- data/generators/language/language_generator.rb +47 -0
- data/generators/language/templates/strings.js +10 -0
- data/generators/model/USAGE +24 -0
- data/generators/model/model_generator.rb +55 -0
- data/generators/model/templates/fixture.js +11 -0
- data/generators/model/templates/model.js +20 -0
- data/generators/model/templates/test.rhtml +21 -0
- data/generators/test/USAGE +16 -0
- data/generators/test/templates/test.rhtml +21 -0
- data/generators/test/test_generator.rb +47 -0
- data/generators/view/USAGE +16 -0
- data/generators/view/templates/test.rhtml +21 -0
- data/generators/view/templates/view.js +20 -0
- data/generators/view/view_generator.rb +51 -0
- data/jsdoc/README.txt +119 -0
- data/jsdoc/app/DocFile.js +137 -0
- data/jsdoc/app/DocTag.js +110 -0
- data/jsdoc/app/Doclet.js +63 -0
- data/jsdoc/app/Dumper.js +143 -0
- data/jsdoc/app/JsDoc.js +103 -0
- data/jsdoc/app/JsHilite.js +45 -0
- data/jsdoc/app/JsIO.js +163 -0
- data/jsdoc/app/JsParse.js +385 -0
- data/jsdoc/app/JsPlate.js +130 -0
- data/jsdoc/app/JsTestrun.js +129 -0
- data/jsdoc/app/JsToke.js +564 -0
- data/jsdoc/app/Symbol.js +298 -0
- data/jsdoc/app/Transformer.js +14 -0
- data/jsdoc/app/Util.js +97 -0
- data/jsdoc/app/js.jar +0 -0
- data/jsdoc/app/run.js +144 -0
- data/jsdoc/plugins/min.js +316 -0
- data/jsdoc/plugins/strip.js +20 -0
- data/jsdoc/templates/sproutcore/class.tmpl +438 -0
- data/jsdoc/templates/sproutcore/default.css +241 -0
- data/jsdoc/templates/sproutcore/index.html +13 -0
- data/jsdoc/templates/sproutcore/index.tmpl +21 -0
- data/jsdoc/templates/sproutcore/prototype.js +4186 -0
- data/jsdoc/templates/sproutcore/publish.js +236 -0
- data/jsdoc/templates/sproutcore/splash.html +7 -0
- data/lib/sproutcore/build_tools/html_builder.rb +88 -0
- data/lib/sproutcore/build_tools/resource_builder.rb +194 -0
- data/lib/sproutcore/build_tools.rb +44 -0
- data/lib/sproutcore/bundle.rb +517 -0
- data/lib/sproutcore/bundle_manifest.rb +397 -0
- data/lib/sproutcore/generator_helper.rb +170 -0
- data/lib/sproutcore/helpers/capture_helper.rb +42 -0
- data/lib/sproutcore/helpers/static_helper.rb +80 -0
- data/lib/sproutcore/helpers/tag_helper.rb +110 -0
- data/lib/sproutcore/helpers/text_helper.rb +336 -0
- data/lib/sproutcore/helpers.rb +3 -0
- data/lib/sproutcore/jsdoc.rb +40 -0
- data/lib/sproutcore/jsmin.rb +247 -0
- data/lib/sproutcore/library.rb +258 -0
- data/lib/sproutcore/merb/bundle_controller.rb +179 -0
- data/lib/sproutcore/merb/router.rb +43 -0
- data/lib/sproutcore/merb.rb +27 -0
- data/lib/sproutcore/version.rb +9 -0
- data/lib/sproutcore/view_helpers/button_views.rb +302 -0
- data/lib/sproutcore/view_helpers/core_views.rb +284 -0
- data/lib/sproutcore/view_helpers/form_views.rb +258 -0
- data/lib/sproutcore/view_helpers/menu_views.rb +94 -0
- data/lib/sproutcore/view_helpers.rb +628 -0
- data/lib/sproutcore.rb +30 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/script/txt2html +74 -0
- data/setup.rb +1585 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +7 -0
- data/spec/sproutcore_spec.rb +11 -0
- data/tasks/deployment.rake +34 -0
- data/tasks/environment.rake +7 -0
- data/tasks/rspec.rake +21 -0
- data/tasks/website.rake +17 -0
- metadata +365 -0
|
@@ -0,0 +1,517 @@
|
|
|
1
|
+
require 'sproutcore/build_tools'
|
|
2
|
+
|
|
3
|
+
module SproutCore
|
|
4
|
+
|
|
5
|
+
# A bundle can map a directory of source files to an output format optimized
|
|
6
|
+
# for delivery on the web. It can also return the URLs to use for a particular client.
|
|
7
|
+
# A Bundle cannot actually build resources for you, but it works in concert with the
|
|
8
|
+
# ResourceBuilder to help you with that.
|
|
9
|
+
#
|
|
10
|
+
# When you create a bundle, you must pass the name of the client and the library the bundle
|
|
11
|
+
# belongs to. The library is used to generate default paths for most resources and to find
|
|
12
|
+
# other bundles.
|
|
13
|
+
#
|
|
14
|
+
# You must provide the following properties to every build:
|
|
15
|
+
#
|
|
16
|
+
# bundle_name:: A name used to identify the client for required URLs, etc.
|
|
17
|
+
# library:: The root URL of the library holding the client
|
|
18
|
+
#
|
|
19
|
+
# The following properties are also required, but have defaults you can rely use:
|
|
20
|
+
#
|
|
21
|
+
# bundle_type:: :framework|:client (default :client)
|
|
22
|
+
# required_bundles:: Names of required frameworks. (default: none)
|
|
23
|
+
# stylesheet_libs:: URLs to requires CSS not managed by the build system. (default: none)
|
|
24
|
+
# javascript_libs:: URLS to requires JavaScript notn managed by the build system (def:non)
|
|
25
|
+
#
|
|
26
|
+
# The following properties are required for the build process but can be generated
|
|
27
|
+
# automatically using other properties you specify:
|
|
28
|
+
#
|
|
29
|
+
# source_root:: The directory containing the source files
|
|
30
|
+
# default: :library_root/pluralize(:build_type)/:bundle_name
|
|
31
|
+
#
|
|
32
|
+
# build_root:: The directory that should contain the built files.
|
|
33
|
+
# default: :public_root/:url_prefix/:bundle_name
|
|
34
|
+
#
|
|
35
|
+
# url_root:: The url that can be used to reach the built resources
|
|
36
|
+
# default: /:url_prefix/:bundle_name
|
|
37
|
+
#
|
|
38
|
+
# index_root:: The root url that can be used to reach retrieve the index.html.
|
|
39
|
+
# default: /:index_prefix/:bundle_name
|
|
40
|
+
#
|
|
41
|
+
# If you do not want to specify all of these options, you can provide the following defaults
|
|
42
|
+
# and the rest will be inferred:
|
|
43
|
+
#
|
|
44
|
+
# library_root:: The root URL for the library. This is computed from the library if
|
|
45
|
+
# you pass one.
|
|
46
|
+
#
|
|
47
|
+
# public_root:: The root directory accessible to the web browser.
|
|
48
|
+
# default: :library_root/public
|
|
49
|
+
#
|
|
50
|
+
# url_prefix:: The prefix to put in front of all resource requests.
|
|
51
|
+
# default: static
|
|
52
|
+
#
|
|
53
|
+
# index_prefix:: The prefix to put in front of all index.html request.
|
|
54
|
+
# default: ''
|
|
55
|
+
#
|
|
56
|
+
# preferred_language:: The default language to use for this bundle. Defaults to :en
|
|
57
|
+
#
|
|
58
|
+
# build_mode:: Determines whether the JS & CSS resources should be combined or
|
|
59
|
+
# linked directly
|
|
60
|
+
#
|
|
61
|
+
# layout: Path to the layout resource. This should be of the form
|
|
62
|
+
# bundle_name:relative_path/to/client. Default: sproutcore:lib/index.html
|
|
63
|
+
#
|
|
64
|
+
class Bundle
|
|
65
|
+
|
|
66
|
+
LONG_LANGUAGE_MAP = { :english => :en, :french => :fr, :german => :de, :japanese => :jp, :spanish => :es, :italian => :it }
|
|
67
|
+
SHORT_LANGUAGE_MAP = { :en => :english, :fr => :french, :de => :german, :jp => :japanese, :es => :spanish, :it => :italian }
|
|
68
|
+
|
|
69
|
+
# The default build mode for bundles. This should be set once before you start using
|
|
70
|
+
# bundles. You can override this when you create a specific bundle, but that should not
|
|
71
|
+
# be the typical behavior
|
|
72
|
+
def self.build_mode; @build_mode || :development; end
|
|
73
|
+
|
|
74
|
+
def self.build_mode=(new_mode); @build_mode = new_mode; end
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
attr_reader :bundle_name, :bundle_type, :required_bundles, :preferred_language
|
|
78
|
+
attr_reader :javascript_libs, :stylesheet_libs
|
|
79
|
+
attr_reader :library, :public_root, :url_prefix, :index_prefix
|
|
80
|
+
attr_reader :source_root, :build_root, :url_root, :index_root
|
|
81
|
+
attr_reader :build_mode, :layout
|
|
82
|
+
|
|
83
|
+
def library_root
|
|
84
|
+
@library_root ||= library.nil? ? nil : library.root_path
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# ==== Returns
|
|
88
|
+
# All bundles required directly or indirectly by this bundles. These are returned in
|
|
89
|
+
# their proper load order.
|
|
90
|
+
#
|
|
91
|
+
def all_required_bundles(seen=nil)
|
|
92
|
+
seen ||= Set.new
|
|
93
|
+
seen << self
|
|
94
|
+
|
|
95
|
+
ret = []
|
|
96
|
+
# before you load me, load my bundles
|
|
97
|
+
required_bundles.each do |name|
|
|
98
|
+
b = library.bundle_for(name)
|
|
99
|
+
next if seen.include?(b)
|
|
100
|
+
raise "Cannot locate required bundle '#{name}' for #{bundle_name}" if b.nil?
|
|
101
|
+
ret += b.all_required_bundles(seen)
|
|
102
|
+
end
|
|
103
|
+
ret << self
|
|
104
|
+
return ret
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# ==== Returns
|
|
108
|
+
# The computed path to the layout rhtml.
|
|
109
|
+
def layout_path
|
|
110
|
+
return @layout_path unless @layout_path.nil?
|
|
111
|
+
bundle_name, entry_name = layout.split(':')
|
|
112
|
+
entry_name, bundle_name = bundle_name, entry_name if entry_name.nil?
|
|
113
|
+
|
|
114
|
+
# Get the bundle. If bundle_name is nil, self
|
|
115
|
+
layout_bundle = bundle_name.nil? ? self : library.bundle_for(bundle_name.to_sym)
|
|
116
|
+
return nil if layout_bundle.nil?
|
|
117
|
+
|
|
118
|
+
# Now look for an entry with that name. This will use the primary language
|
|
119
|
+
# since we do not support localized layouts.
|
|
120
|
+
entry = layout_bundle.entry_for(entry_name, :hidden => :include)
|
|
121
|
+
|
|
122
|
+
# If the entry was not found, then we don't have a layout. Oh no!
|
|
123
|
+
if entry.nil?
|
|
124
|
+
raise "Could not find layout named #{entry_name} in bundle #{layout_bundle.bundle_name}!"
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# The return value if the source_path of the entry.
|
|
128
|
+
@layout_path = entry.source_path
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
# Returns the root URL to the current library.
|
|
132
|
+
def initialize(bundle_name, opts ={})
|
|
133
|
+
|
|
134
|
+
# You must provide the following properties to every build:
|
|
135
|
+
# bundle_name:: A name used to identify the client for required URLs, etc.
|
|
136
|
+
@bundle_name = bundle_name.to_sym
|
|
137
|
+
|
|
138
|
+
# The following are not required by the build system, but they can be used to
|
|
139
|
+
# automatically construct the key paths listed below. Often times defaults will
|
|
140
|
+
# do the right thing
|
|
141
|
+
#
|
|
142
|
+
# library:: The root URL of the library holding the client
|
|
143
|
+
@library = opts[:library]
|
|
144
|
+
@library_root = opts[:library_root]
|
|
145
|
+
raise "Bundles must belong to a library or have a library_root" if library_root.nil?
|
|
146
|
+
|
|
147
|
+
# The following properties are also required, but have defaults you can rely use:
|
|
148
|
+
# bundle_type:: :framework|:client (default :client)
|
|
149
|
+
@bundle_type = (opts[:bundle_type] || opts[:type] || :client).to_sym
|
|
150
|
+
|
|
151
|
+
# dependencies:: Names of required frameworks. (default: :sproutapp)
|
|
152
|
+
@required_bundles = opts[:required_bundles] || opts[:required] || []
|
|
153
|
+
|
|
154
|
+
# preferred_language:: The default language to use for this bundle.
|
|
155
|
+
@preferred_language = (opts[:preferred_language] || opts[:language] || :en).to_sym
|
|
156
|
+
|
|
157
|
+
# javacript_libs:: External required libraries.
|
|
158
|
+
@javascript_libs = opts[:javascript_libs] || opts[:js_libs] || []
|
|
159
|
+
|
|
160
|
+
# stylesheet_libs:: External required stylesheet library
|
|
161
|
+
@stylesheet_libs = opts[:stylesheet_libs] || opts[:css_libs] || []
|
|
162
|
+
|
|
163
|
+
# public_root:: The root directory accessible to the web browser.
|
|
164
|
+
@public_root = normalize_path(opts[:public_root] || 'public')
|
|
165
|
+
#
|
|
166
|
+
# url_prefix:: The prefix to put in front of all resource requests.
|
|
167
|
+
@url_prefix = opts[:url_prefix] || opts[:resources_at] || opts[:at] || 'static'
|
|
168
|
+
#
|
|
169
|
+
# index_prefix:: The prefix to put in front of all index.html request.
|
|
170
|
+
@index_prefix = opts[:index_prefix] || opts[:index_at] || ''
|
|
171
|
+
|
|
172
|
+
# The following properties are required for the build process but can be generated
|
|
173
|
+
# automatically using other properties you specify:
|
|
174
|
+
# source_root:: The directory containing the source files
|
|
175
|
+
@source_root = normalize_path(opts[:source_root] || File.join(bundle_type.to_s.pluralize, bundle_name.to_s))
|
|
176
|
+
|
|
177
|
+
# build_root:: The directory that should contain the built files.
|
|
178
|
+
@build_root = normalize_path(opts[:build_root] || File.join(public_root, url_prefix.to_s, bundle_name.to_s))
|
|
179
|
+
|
|
180
|
+
# url_root:: The url that can be used to reach the built resources
|
|
181
|
+
@url_root = opts[:url_root] || ['', (url_prefix.nil? || url_prefix.size==0) ? nil : url_prefix, bundle_name.to_s].compact.join('/')
|
|
182
|
+
|
|
183
|
+
# index_root:: The root url that can be used to reach retrieve the index.html.
|
|
184
|
+
@index_root = opts[:index_root] || ['',(index_prefix.nil? || index_prefix.size==0) ? nil : index_prefix, bundle_name.to_s].compact.join('/')
|
|
185
|
+
|
|
186
|
+
# build_mode:: The build mode to use when combining resources.
|
|
187
|
+
@build_mode = opts[:build_mode] || SproutCore::Bundle.build_mode
|
|
188
|
+
|
|
189
|
+
# layout: Path to the layout resource. This should be of the form
|
|
190
|
+
@layout = opts[:layout] || 'sproutcore:lib/index.rhtml'
|
|
191
|
+
|
|
192
|
+
reload!
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
######################################################
|
|
196
|
+
## RETRIEVING RESOURCES
|
|
197
|
+
##
|
|
198
|
+
|
|
199
|
+
# ==== Returns
|
|
200
|
+
# The array of stylesheet entries sorted in load order.
|
|
201
|
+
def sorted_stylesheet_entries(opts = {})
|
|
202
|
+
opts[:language] ||= preferred_language
|
|
203
|
+
entries = entries_for(:stylesheet, opts)
|
|
204
|
+
BuildTools::ResourceBuilder.sort_entries_by_load_order(entries, opts[:language], self)
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
# ==== Returns
|
|
208
|
+
# The array of javascript entries sorted in load order.
|
|
209
|
+
def sorted_javascript_entries(opts = {})
|
|
210
|
+
opts[:language] ||= preferred_language
|
|
211
|
+
entries = entries_for(:javascript, opts)
|
|
212
|
+
BuildTools::JavaScriptResourceBuilder.sort_entries_by_load_order(entries, opts[:language], self)
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
# This method returns the manifest entries for resources of the specified type.
|
|
216
|
+
#
|
|
217
|
+
# ==== Params
|
|
218
|
+
# type:: must be one of :javascript, :stylesheet, :resource, :html, :fixture, :test
|
|
219
|
+
#
|
|
220
|
+
# ==== Options
|
|
221
|
+
# language:: The language to use. Defaults to preferred language.
|
|
222
|
+
# hidden:: Can be :none|:include|:only
|
|
223
|
+
#
|
|
224
|
+
def entries_for(resource_type, opts={})
|
|
225
|
+
with_hidden = opts[:hidden] || :none
|
|
226
|
+
manifest = manifest_for(opts[:language] || preferred_language)
|
|
227
|
+
ret = manifest.entries_for(resource_type)
|
|
228
|
+
|
|
229
|
+
case with_hidden
|
|
230
|
+
when :none
|
|
231
|
+
ret = ret.reject { |x| x.hidden }
|
|
232
|
+
when :only
|
|
233
|
+
ret = ret.reject { |x| !x.hidden }
|
|
234
|
+
end
|
|
235
|
+
return ret
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
# This method returns the manifest entry for a resource with the specified name.
|
|
239
|
+
#
|
|
240
|
+
# ==== Params
|
|
241
|
+
# name: The name of the entry.
|
|
242
|
+
#
|
|
243
|
+
# ==== Options
|
|
244
|
+
# language:: The language to use. Defaults to preferred language
|
|
245
|
+
# hidden:: Can be :none|:include|:only
|
|
246
|
+
#
|
|
247
|
+
def entry_for(resource_name, opts={})
|
|
248
|
+
with_hidden = opts[:hidden] || :none
|
|
249
|
+
manifest = manifest_for(opts[:language] || preferred_language)
|
|
250
|
+
ret = manifest.entry_for(resource_name)
|
|
251
|
+
|
|
252
|
+
case with_hidden
|
|
253
|
+
when :none
|
|
254
|
+
ret = nil if ret && ret.hidden?
|
|
255
|
+
when :only
|
|
256
|
+
ret = nil unless ret && ret.hidden?
|
|
257
|
+
end
|
|
258
|
+
return ret
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
# Returns the entry for the specified URL. This will extract the language from the URL.
|
|
262
|
+
#
|
|
263
|
+
# ==== Params
|
|
264
|
+
# url<String>:: The url
|
|
265
|
+
#
|
|
266
|
+
# ==== Options
|
|
267
|
+
# hidden:: Use :include,:none,:only to control hidden options
|
|
268
|
+
# language:: Explicitly include the language. Leave this out to autodetect from URL.
|
|
269
|
+
#
|
|
270
|
+
def entry_for_url(url, opts={})
|
|
271
|
+
# get the language
|
|
272
|
+
opts[:language] ||= url.match(/^#{url_root}\/([^\/]+)\//).to_a[1] || preferred_language
|
|
273
|
+
entries(opts).each do |entry|
|
|
274
|
+
return entry if entry.url == url
|
|
275
|
+
end
|
|
276
|
+
return nil # not found!
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
# Helper method. This will normalize a URL into one that can map directly to an
|
|
280
|
+
# entry in the bundle. If the URL is of a format that cannot be converted, returns nil.
|
|
281
|
+
#
|
|
282
|
+
# ==== Params
|
|
283
|
+
# url<String>:: The URL
|
|
284
|
+
#
|
|
285
|
+
def normalize_url(url)
|
|
286
|
+
|
|
287
|
+
# Get the default index.
|
|
288
|
+
if (url == index_root)
|
|
289
|
+
url = [index_root, preferred_language.to_s, 'index.html'].join('/')
|
|
290
|
+
|
|
291
|
+
# Requests to url_root/lang should have index.html appended to them
|
|
292
|
+
elsif /^#{index_root}\/[^\/\.]+$/ =~ url
|
|
293
|
+
url << '/index.html'
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
return url
|
|
297
|
+
end
|
|
298
|
+
|
|
299
|
+
# Returns all of the entries for the manifest.
|
|
300
|
+
#
|
|
301
|
+
# ==== Options
|
|
302
|
+
# language:: The language to use. Defaults to preferred language
|
|
303
|
+
# hidden:: Can be :none|:include|:only
|
|
304
|
+
#
|
|
305
|
+
def entries(opts ={})
|
|
306
|
+
with_hidden = opts[:hidden] || :none
|
|
307
|
+
manifest = manifest_for(opts[:language] || preferred_language)
|
|
308
|
+
ret = manifest.entries
|
|
309
|
+
|
|
310
|
+
case with_hidden
|
|
311
|
+
when :none
|
|
312
|
+
ret = ret.reject { |x| x.hidden }
|
|
313
|
+
when :only
|
|
314
|
+
ret = ret.reject { |x| !x.hidden }
|
|
315
|
+
end
|
|
316
|
+
return ret
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
# Does a deep search of the entries, looking for a resource that is a close
|
|
320
|
+
# match of the specified resource. This does not need to match the filename
|
|
321
|
+
# exactly and it can omit the extension
|
|
322
|
+
def find_resource_entry(filename, opts={})
|
|
323
|
+
extname = File.extname(filename)
|
|
324
|
+
rootname = filename.gsub(/#{extname}$/,'')
|
|
325
|
+
entry_extname = entry_rootname = nil
|
|
326
|
+
|
|
327
|
+
ret = entries_for(:resource, opts.merge(:hidden => :none)).reject do |entry|
|
|
328
|
+
entry_extname = File.extname(entry.filename)
|
|
329
|
+
entry_rootname = entry.filename.gsub(/#{entry_extname}$/,'')
|
|
330
|
+
|
|
331
|
+
ext_match = (extname.nil? || extname.size == 0) || (entry_extname == extname)
|
|
332
|
+
!(ext_match && (/#{rootname}$/ =~ entry_rootname))
|
|
333
|
+
end
|
|
334
|
+
|
|
335
|
+
ret.first
|
|
336
|
+
end
|
|
337
|
+
|
|
338
|
+
# Builds the passed array of entries. If the entry is already built, then this
|
|
339
|
+
# method does nothing unless force => true
|
|
340
|
+
#
|
|
341
|
+
# The exact action taken by this method varies by resource type. Some resources
|
|
342
|
+
# will simply be copied. Others will actually be compiled.
|
|
343
|
+
#
|
|
344
|
+
# ==== Params
|
|
345
|
+
#
|
|
346
|
+
# entries:: The entries to build
|
|
347
|
+
#
|
|
348
|
+
# ==== Options
|
|
349
|
+
#
|
|
350
|
+
# force:: If true then the entry will be built again, even if it already exists.
|
|
351
|
+
# hidden:: Set to :none, :include, or :only
|
|
352
|
+
#
|
|
353
|
+
def build_entries(entries, opts={})
|
|
354
|
+
|
|
355
|
+
with_hidden = opts[:hidden] || :none
|
|
356
|
+
|
|
357
|
+
# First, start an "already seen" set.
|
|
358
|
+
created_seen = @seen.nil?
|
|
359
|
+
@seen ||= Set.new
|
|
360
|
+
|
|
361
|
+
# Now, process the entries, adding them to the seen set.
|
|
362
|
+
entries.each do |entry|
|
|
363
|
+
|
|
364
|
+
# skip if hidden, already seen, or already built (unless forced)
|
|
365
|
+
if entry.hidden? && with_hidden == :none
|
|
366
|
+
SC.logger.debug("~ Skipping Entry: #{entry.filename} because it is hidden") and next
|
|
367
|
+
end
|
|
368
|
+
|
|
369
|
+
if !entry.hidden? && with_hidden == :only
|
|
370
|
+
SC.logger.debug("~ Skipping Entry: #{entry.filename} because it is not hidden") and next
|
|
371
|
+
end
|
|
372
|
+
|
|
373
|
+
# Nothing interesting to log here.
|
|
374
|
+
next if @seen.include?(entry)
|
|
375
|
+
@seen << entry
|
|
376
|
+
|
|
377
|
+
# Do not build if file exists and source paths are not newer.
|
|
378
|
+
if !opts[:force] && File.exists?(entry.build_path)
|
|
379
|
+
source_mtime = entry.source_path_mtime
|
|
380
|
+
if source_mtime && (File.mtime(entry.build_path) >= source_mtime)
|
|
381
|
+
SC.logger.debug("~ Skipping Entry: #{entry.filename} because it has not changed") and next
|
|
382
|
+
end
|
|
383
|
+
end
|
|
384
|
+
|
|
385
|
+
|
|
386
|
+
# OK, looks like this is ready to be built.
|
|
387
|
+
if entry.use_symlink?
|
|
388
|
+
SC.logger.debug("~ Creating Symlink: #{entry.filename}")
|
|
389
|
+
BuildTools.build_symlink(entry, self)
|
|
390
|
+
else
|
|
391
|
+
SC.logger.debug("~ Building #{entry.type.to_s.capitalize}: #{entry.filename}")
|
|
392
|
+
BuildTools.send("build_#{entry.type}".to_sym, entry, self)
|
|
393
|
+
end
|
|
394
|
+
end
|
|
395
|
+
|
|
396
|
+
# Clean up the seen set when we exit.
|
|
397
|
+
@seen = nil if created_seen
|
|
398
|
+
end
|
|
399
|
+
|
|
400
|
+
# Easy singular form of build_entries(). Take same parameters except for a single entry
|
|
401
|
+
# instead of an array.
|
|
402
|
+
def build_entry(entry, opts={})
|
|
403
|
+
build_entries([entry], opts)
|
|
404
|
+
end
|
|
405
|
+
|
|
406
|
+
# Invoked by build tools when they build a dependent entry. This will add the entry
|
|
407
|
+
# to the list of seen entries during a build so that it will not be rebuilt.
|
|
408
|
+
def did_build_entry(entry)
|
|
409
|
+
@seen << entry unless @seen.nil?
|
|
410
|
+
end
|
|
411
|
+
|
|
412
|
+
# This will perform a complete build for the named language
|
|
413
|
+
def build_language(language)
|
|
414
|
+
SC.logger.info("~ Language: #{language}")
|
|
415
|
+
build_entries(entries(:language => language))
|
|
416
|
+
SC.logger.debug("~ Done.\n")
|
|
417
|
+
end
|
|
418
|
+
|
|
419
|
+
# This will perform a complete build for all languages that have a matching lproj.
|
|
420
|
+
# You can also pass in an array of languages you would like to build
|
|
421
|
+
def build(*languages)
|
|
422
|
+
|
|
423
|
+
# Get the installed languages (and the preferred language, just in case)
|
|
424
|
+
languages = languages.flatten
|
|
425
|
+
languages = installed_languages if languages.nil? || languages.size == 0
|
|
426
|
+
languages.uniq!
|
|
427
|
+
|
|
428
|
+
SC.logger.debug("~ Build Mode: #{build_mode}")
|
|
429
|
+
SC.logger.debug("~ Source Root: #{source_root}")
|
|
430
|
+
SC.logger.debug("~ Build Root: #{build_root}")
|
|
431
|
+
|
|
432
|
+
languages.uniq.each { |lang| build_language(lang) }
|
|
433
|
+
|
|
434
|
+
# After build is complete, try to copy the index.html file of the preferred language
|
|
435
|
+
# to the build_root
|
|
436
|
+
index_entry = entry_for('index.html', :language => preferred_language)
|
|
437
|
+
if index_entry && File.exists?(index_entry.build_path)
|
|
438
|
+
FileUtils.mkdir_p(build_root)
|
|
439
|
+
FileUtils.cp_r(index_entry.build_path, File.join(build_root,'index.html'))
|
|
440
|
+
end
|
|
441
|
+
end
|
|
442
|
+
|
|
443
|
+
######################################################
|
|
444
|
+
## MANIFESTS
|
|
445
|
+
##
|
|
446
|
+
|
|
447
|
+
# Invoke this method whenever you think the bundle's contents on disk might have changed
|
|
448
|
+
# this will throw away any cached information in bundle. This is generally a cheap
|
|
449
|
+
# operation so it is OK to call it often, though it will be less performant overall.
|
|
450
|
+
def reload!
|
|
451
|
+
@manifests = {}
|
|
452
|
+
end
|
|
453
|
+
|
|
454
|
+
# Returns the bundle manifest for the specified language. The manifest will be created
|
|
455
|
+
# if it does not yet exist.
|
|
456
|
+
def manifest_for(language)
|
|
457
|
+
@manifests[language.to_sym] ||= BundleManifest.new(self, language.to_sym)
|
|
458
|
+
end
|
|
459
|
+
|
|
460
|
+
# ==== Returns
|
|
461
|
+
# Languages installed in the source directory
|
|
462
|
+
#
|
|
463
|
+
def installed_languages
|
|
464
|
+
ret = Dir.glob(File.join(source_root,'*.lproj')).map do |x|
|
|
465
|
+
x.match(/([^\/]+)\.lproj$/).to_a[1]
|
|
466
|
+
end
|
|
467
|
+
ret << preferred_language
|
|
468
|
+
ret.compact.map { |x| LONG_LANGUAGE_MAP[x.to_sym] || x.to_sym }.uniq
|
|
469
|
+
end
|
|
470
|
+
|
|
471
|
+
# Finds the actual lproj directory (in the source) for the language code. If the named
|
|
472
|
+
# language does not exist, returns the lproj for the preferred language.
|
|
473
|
+
def lproj_for(language)
|
|
474
|
+
|
|
475
|
+
# try language as passed in.
|
|
476
|
+
ret = "#{language}.lproj"
|
|
477
|
+
return ret if File.exists?(File.join(source_root,ret))
|
|
478
|
+
|
|
479
|
+
# failed, try to map to long language
|
|
480
|
+
if long_language = SHORT_LANGUAGE_MAP[language.to_sym]
|
|
481
|
+
ret = "#{long_language}.lproj"
|
|
482
|
+
return ret if File.exists?(File.join(source_root,ret))
|
|
483
|
+
end
|
|
484
|
+
|
|
485
|
+
# failed, try to map to short language
|
|
486
|
+
if short_language = LONG_LANGUAGE_MAP[language.to_sym]
|
|
487
|
+
ret = "#{short_language}.lproj"
|
|
488
|
+
return ret if File.exists?(File.join(source_root,ret))
|
|
489
|
+
end
|
|
490
|
+
|
|
491
|
+
# failed, return using preferred_language unless this is the preferred language
|
|
492
|
+
ret = (language != preferred_language) ? lproj_for(preferred_language) : nil
|
|
493
|
+
return ret unless ret.nil?
|
|
494
|
+
|
|
495
|
+
# Super-ultra massive fail. Possible that no localized resources exist at all.
|
|
496
|
+
# Return english.lproj and hope for the best
|
|
497
|
+
return 'english.lproj'
|
|
498
|
+
end
|
|
499
|
+
|
|
500
|
+
# Used by the bundle manifest. Only true if bundle_type is client
|
|
501
|
+
def can_have_html?
|
|
502
|
+
return bundle_type == :client
|
|
503
|
+
end
|
|
504
|
+
|
|
505
|
+
protected
|
|
506
|
+
|
|
507
|
+
# Converts the named path to a fully qualified path name using the library root, if it
|
|
508
|
+
# does not begin with a slash
|
|
509
|
+
def normalize_path(path)
|
|
510
|
+
(path[0] == '/'[0]) ? path : File.join(library_root, path)
|
|
511
|
+
end
|
|
512
|
+
|
|
513
|
+
end
|
|
514
|
+
|
|
515
|
+
end
|
|
516
|
+
|
|
517
|
+
|