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,110 @@
|
|
|
1
|
+
require 'cgi'
|
|
2
|
+
require 'erb'
|
|
3
|
+
|
|
4
|
+
# Borrowed from Rails 2.0.2
|
|
5
|
+
|
|
6
|
+
module SproutCore
|
|
7
|
+
module Helpers #:nodoc:
|
|
8
|
+
# Use these methods to generate HTML tags programmatically when you can't use
|
|
9
|
+
# a Builder. By default, they output XHTML compliant tags.
|
|
10
|
+
module TagHelper
|
|
11
|
+
include ERB::Util
|
|
12
|
+
|
|
13
|
+
# Returns an empty HTML tag of type +name+ which by default is XHTML
|
|
14
|
+
# compliant. Setting +open+ to true will create an open tag compatible
|
|
15
|
+
# with HTML 4.0 and below. Add HTML attributes by passing an attributes
|
|
16
|
+
# hash to +options+. For attributes with no value like (disabled and
|
|
17
|
+
# readonly), give it a value of true in the +options+ hash. You can use
|
|
18
|
+
# symbols or strings for the attribute names.
|
|
19
|
+
#
|
|
20
|
+
# tag("br")
|
|
21
|
+
# # => <br />
|
|
22
|
+
# tag("br", nil, true)
|
|
23
|
+
# # => <br>
|
|
24
|
+
# tag("input", { :type => 'text', :disabled => true })
|
|
25
|
+
# # => <input type="text" disabled="disabled" />
|
|
26
|
+
def tag(name, options = nil, open = false)
|
|
27
|
+
"<#{name}#{tag_options(options) if options}" + (open ? ">" : " />")
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Returns an HTML block tag of type +name+ surrounding the +content+. Add
|
|
31
|
+
# HTML attributes by passing an attributes hash to +options+. For attributes
|
|
32
|
+
# with no value like (disabled and readonly), give it a value of true in
|
|
33
|
+
# the +options+ hash. You can use symbols or strings for the attribute names.
|
|
34
|
+
#
|
|
35
|
+
# content_tag(:p, "Hello world!")
|
|
36
|
+
# # => <p>Hello world!</p>
|
|
37
|
+
# content_tag(:div, content_tag(:p, "Hello world!"), :class => "strong")
|
|
38
|
+
# # => <div class="strong"><p>Hello world!</p></div>
|
|
39
|
+
# content_tag("select", options, :multiple => true)
|
|
40
|
+
# # => <select multiple="multiple">...options...</select>
|
|
41
|
+
#
|
|
42
|
+
# Instead of passing the content as an argument, you can also use a block
|
|
43
|
+
# in which case, you pass your +options+ as the second parameter.
|
|
44
|
+
#
|
|
45
|
+
# <% content_tag :div, :class => "strong" do -%>
|
|
46
|
+
# Hello world!
|
|
47
|
+
# <% end -%>
|
|
48
|
+
# # => <div class="strong"><p>Hello world!</p></div>
|
|
49
|
+
def content_tag(name, content_or_options_with_block = nil, options = nil, &block)
|
|
50
|
+
if block_given?
|
|
51
|
+
options = content_or_options_with_block if content_or_options_with_block.is_a?(Hash)
|
|
52
|
+
content = capture(&block)
|
|
53
|
+
content_tag = content_tag_string(name, content, options)
|
|
54
|
+
block_is_within_action_view?(block) ? concat(content_tag, block.binding) : content_tag
|
|
55
|
+
else
|
|
56
|
+
content = content_or_options_with_block
|
|
57
|
+
content_tag_string(name, content, options)
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Returns a CDATA section with the given +content+. CDATA sections
|
|
62
|
+
# are used to escape blocks of text containing characters which would
|
|
63
|
+
# otherwise be recognized as markup. CDATA sections begin with the string
|
|
64
|
+
# <tt><![CDATA[</tt> and end with (and may not contain) the string <tt>]]></tt>.
|
|
65
|
+
#
|
|
66
|
+
# cdata_section("<hello world>")
|
|
67
|
+
# # => <![CDATA[<hello world>]]>
|
|
68
|
+
def cdata_section(content)
|
|
69
|
+
"<![CDATA[#{content}]]>"
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Returns the escaped +html+ without affecting existing escaped entities.
|
|
73
|
+
#
|
|
74
|
+
# escape_once("1 > 2 & 3")
|
|
75
|
+
# # => "1 < 2 & 3"
|
|
76
|
+
def escape_once(html)
|
|
77
|
+
fix_double_escape(html_escape(html.to_s))
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
private
|
|
81
|
+
def content_tag_string(name, content, options)
|
|
82
|
+
tag_options = options ? tag_options(options) : ""
|
|
83
|
+
"<#{name}#{tag_options}>#{content}</#{name}>"
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def tag_options(options)
|
|
87
|
+
cleaned_options = convert_booleans(options.stringify_keys.reject {|key, value| value.nil?})
|
|
88
|
+
' ' + cleaned_options.map {|key, value| %(#{key}="#{escape_once(value)}")}.sort * ' ' unless cleaned_options.empty?
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def convert_booleans(options)
|
|
92
|
+
%w( disabled readonly multiple ).each { |a| boolean_attribute(options, a) }
|
|
93
|
+
options
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def boolean_attribute(options, attribute)
|
|
97
|
+
options[attribute] ? options[attribute] = attribute : options.delete(attribute)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# Fix double-escaped entities, such as &amp;, &#123;, etc.
|
|
101
|
+
def fix_double_escape(escaped)
|
|
102
|
+
escaped.gsub(/&([a-z]+|(#\d+));/i) { "&#{$1};" }
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def block_is_within_action_view?(block)
|
|
106
|
+
eval("defined? _erbout", block.binding)
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
require 'sproutcore/helpers/tag_helper'
|
|
2
|
+
#require 'html/document'
|
|
3
|
+
|
|
4
|
+
# Borrowed from Rails 2.0.2
|
|
5
|
+
|
|
6
|
+
module SproutCore
|
|
7
|
+
module Helpers #:nodoc:
|
|
8
|
+
# The TextHelper Module provides a set of methods for filtering, formatting
|
|
9
|
+
# and transforming strings that can reduce the amount of inline Ruby code in
|
|
10
|
+
# your views. These helper methods extend ActionView making them callable
|
|
11
|
+
# within your template files as shown in the following example which truncates
|
|
12
|
+
# the title of each post to 10 characters.
|
|
13
|
+
#
|
|
14
|
+
# <% @posts.each do |post| %>
|
|
15
|
+
# # post == 'This is my title'
|
|
16
|
+
# Title: <%= truncate(post.title, 10) %>
|
|
17
|
+
# <% end %>
|
|
18
|
+
# => Title: This is my...
|
|
19
|
+
module TextHelper
|
|
20
|
+
# The preferred method of outputting text in your views is to use the
|
|
21
|
+
# <%= "text" %> eRuby syntax. The regular _puts_ and _print_ methods
|
|
22
|
+
# do not operate as expected in an eRuby code block. If you absolutely must
|
|
23
|
+
# output text within a code block, you can use the concat method.
|
|
24
|
+
#
|
|
25
|
+
# <% concat "hello", binding %>
|
|
26
|
+
# is equivalent to using:
|
|
27
|
+
# <%= "hello" %>
|
|
28
|
+
def concat(string, binding)
|
|
29
|
+
eval('_buf', binding) << string
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# If +text+ is longer than +length+, +text+ will be truncated to the length of
|
|
33
|
+
# +length+ and the last three characters will be replaced with the +truncate_string+.
|
|
34
|
+
#
|
|
35
|
+
# truncate("Once upon a time in a world far far away", 14)
|
|
36
|
+
# => Once upon a...
|
|
37
|
+
def truncate(text, length = 30, truncate_string = "...")
|
|
38
|
+
if text.nil? then return end
|
|
39
|
+
l = length - truncate_string.chars.length
|
|
40
|
+
(text.chars.length > length ? text.chars[0...l] + truncate_string : text).to_s
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Highlights one or more +phrases+ everywhere in +text+ by inserting it into
|
|
44
|
+
# a +highlighter+ string. The highlighter can be specialized by passing +highlighter+
|
|
45
|
+
# as a single-quoted string with \1 where the phrase is to be inserted.
|
|
46
|
+
#
|
|
47
|
+
# highlight('You searched for: rails', 'rails')
|
|
48
|
+
# # => You searched for: <strong class="highlight">rails</strong>
|
|
49
|
+
#
|
|
50
|
+
# highlight('You searched for: rails', ['for', 'rails'], '<em>\1</em>')
|
|
51
|
+
# # => You searched <em>for</em>: <em>rails</em>
|
|
52
|
+
def highlight(text, phrases, highlighter = '<strong class="highlight">\1</strong>')
|
|
53
|
+
if text.blank? || phrases.blank?
|
|
54
|
+
text
|
|
55
|
+
else
|
|
56
|
+
match = Array(phrases).map { |p| Regexp.escape(p) }.join('|')
|
|
57
|
+
text.gsub(/(#{match})/i, highlighter)
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Extracts an excerpt from +text+ that matches the first instance of +phrase+.
|
|
62
|
+
# The +radius+ expands the excerpt on each side of +phrase+ by the number of characters
|
|
63
|
+
# defined in +radius+. If the excerpt radius overflows the beginning or end of the +text+,
|
|
64
|
+
# then the +excerpt_string+ will be prepended/appended accordingly. If the +phrase+
|
|
65
|
+
# isn't found, nil is returned.
|
|
66
|
+
#
|
|
67
|
+
# excerpt('This is an example', 'an', 5)
|
|
68
|
+
# => "...s is an examp..."
|
|
69
|
+
#
|
|
70
|
+
# excerpt('This is an example', 'is', 5)
|
|
71
|
+
# => "This is an..."
|
|
72
|
+
def excerpt(text, phrase, radius = 100, excerpt_string = "...")
|
|
73
|
+
if text.nil? || phrase.nil? then return end
|
|
74
|
+
phrase = Regexp.escape(phrase)
|
|
75
|
+
|
|
76
|
+
if found_pos = text.chars =~ /(#{phrase})/i
|
|
77
|
+
start_pos = [ found_pos - radius, 0 ].max
|
|
78
|
+
end_pos = [ found_pos + phrase.chars.length + radius, text.chars.length ].min
|
|
79
|
+
|
|
80
|
+
prefix = start_pos > 0 ? excerpt_string : ""
|
|
81
|
+
postfix = end_pos < text.chars.length ? excerpt_string : ""
|
|
82
|
+
|
|
83
|
+
prefix + text.chars[start_pos..end_pos].strip + postfix
|
|
84
|
+
else
|
|
85
|
+
nil
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# Attempts to pluralize the +singular+ word unless +count+ is 1. If +plural+
|
|
90
|
+
# is supplied, it will use that when count is > 1, if the ActiveSupport Inflector
|
|
91
|
+
# is loaded, it will use the Inflector to determine the plural form, otherwise
|
|
92
|
+
# it will just add an 's' to the +singular+ word.
|
|
93
|
+
#
|
|
94
|
+
# pluralize(1, 'person') => 1 person
|
|
95
|
+
# pluralize(2, 'person') => 2 people
|
|
96
|
+
# pluralize(3, 'person', 'users') => 3 users
|
|
97
|
+
def pluralize(count, singular, plural = nil)
|
|
98
|
+
"#{count || 0} " + if count == 1 || count == '1'
|
|
99
|
+
singular
|
|
100
|
+
elsif plural
|
|
101
|
+
plural
|
|
102
|
+
elsif Object.const_defined?("Inflector")
|
|
103
|
+
Inflector.pluralize(singular)
|
|
104
|
+
else
|
|
105
|
+
singular + "s"
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# Wraps the +text+ into lines no longer than +line_width+ width. This method
|
|
110
|
+
# breaks on the first whitespace character that does not exceed +line_width+.
|
|
111
|
+
#
|
|
112
|
+
# word_wrap('Once upon a time', 4)
|
|
113
|
+
# => Once\nupon\na\ntime
|
|
114
|
+
def word_wrap(text, line_width = 80)
|
|
115
|
+
text.gsub(/\n/, "\n\n").gsub(/(.{1,#{line_width}})(\s+|$)/, "\\1\n").strip
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
begin
|
|
119
|
+
require_library_or_gem "redcloth" unless Object.const_defined?(:RedCloth)
|
|
120
|
+
|
|
121
|
+
# Returns the text with all the Textile codes turned into HTML tags.
|
|
122
|
+
# <i>This method is only available if RedCloth[http://whytheluckystiff.net/ruby/redcloth/]
|
|
123
|
+
# is available</i>.
|
|
124
|
+
def textilize(text)
|
|
125
|
+
if text.blank?
|
|
126
|
+
""
|
|
127
|
+
else
|
|
128
|
+
textilized = RedCloth.new(text, [ :hard_breaks ])
|
|
129
|
+
textilized.hard_breaks = true if textilized.respond_to?("hard_breaks=")
|
|
130
|
+
textilized.to_html
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# Returns the text with all the Textile codes turned into HTML tags,
|
|
135
|
+
# but without the bounding <p> tag that RedCloth adds.
|
|
136
|
+
# <i>This method is only available if RedCloth[http://whytheluckystiff.net/ruby/redcloth/]
|
|
137
|
+
# is available</i>.
|
|
138
|
+
def textilize_without_paragraph(text)
|
|
139
|
+
textiled = textilize(text)
|
|
140
|
+
if textiled[0..2] == "<p>" then textiled = textiled[3..-1] end
|
|
141
|
+
if textiled[-4..-1] == "</p>" then textiled = textiled[0..-5] end
|
|
142
|
+
return textiled
|
|
143
|
+
end
|
|
144
|
+
rescue LoadError
|
|
145
|
+
# We can't really help what's not there
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
begin
|
|
149
|
+
require_library_or_gem "bluecloth" unless Object.const_defined?(:BlueCloth)
|
|
150
|
+
|
|
151
|
+
# Returns the text with all the Markdown codes turned into HTML tags.
|
|
152
|
+
# <i>This method is only available if BlueCloth[http://www.deveiate.org/projects/BlueCloth]
|
|
153
|
+
# is available</i>.
|
|
154
|
+
def markdown(text)
|
|
155
|
+
text.blank? ? "" : BlueCloth.new(text).to_html
|
|
156
|
+
end
|
|
157
|
+
rescue LoadError
|
|
158
|
+
# We can't really help what's not there
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
# Returns +text+ transformed into HTML using simple formatting rules.
|
|
162
|
+
# Two or more consecutive newlines(<tt>\n\n</tt>) are considered as a
|
|
163
|
+
# paragraph and wrapped in <tt><p></tt> tags. One newline (<tt>\n</tt>) is
|
|
164
|
+
# considered as a linebreak and a <tt><br /></tt> tag is appended. This
|
|
165
|
+
# method does not remove the newlines from the +text+.
|
|
166
|
+
def simple_format(text)
|
|
167
|
+
content_tag 'p', text.to_s.
|
|
168
|
+
gsub(/\r\n?/, "\n"). # \r\n and \r -> \n
|
|
169
|
+
gsub(/\n\n+/, "</p>\n\n<p>"). # 2+ newline -> paragraph
|
|
170
|
+
gsub(/([^\n]\n)(?=[^\n])/, '\1<br />') # 1 newline -> br
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
# Turns all urls and email addresses into clickable links. The +link+ parameter
|
|
174
|
+
# will limit what should be linked. You can add html attributes to the links using
|
|
175
|
+
# +href_options+. Options for +link+ are <tt>:all</tt> (default),
|
|
176
|
+
# <tt>:email_addresses</tt>, and <tt>:urls</tt>.
|
|
177
|
+
#
|
|
178
|
+
# auto_link("Go to http://www.rubyonrails.org and say hello to david@loudthinking.com") =>
|
|
179
|
+
# Go to <a href="http://www.rubyonrails.org">http://www.rubyonrails.org</a> and
|
|
180
|
+
# say hello to <a href="mailto:david@loudthinking.com">david@loudthinking.com</a>
|
|
181
|
+
#
|
|
182
|
+
# If a block is given, each url and email address is yielded and the
|
|
183
|
+
# result is used as the link text.
|
|
184
|
+
#
|
|
185
|
+
# auto_link(post.body, :all, :target => '_blank') do |text|
|
|
186
|
+
# truncate(text, 15)
|
|
187
|
+
# end
|
|
188
|
+
def auto_link(text, link = :all, href_options = {}, &block)
|
|
189
|
+
return '' if text.blank?
|
|
190
|
+
case link
|
|
191
|
+
when :all then auto_link_urls(auto_link_email_addresses(text, &block), href_options, &block)
|
|
192
|
+
when :email_addresses then auto_link_email_addresses(text, &block)
|
|
193
|
+
when :urls then auto_link_urls(text, href_options, &block)
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
# Strips link tags from +text+ leaving just the link label.
|
|
198
|
+
#
|
|
199
|
+
# strip_links('<a href="http://www.rubyonrails.org">Ruby on Rails</a>')
|
|
200
|
+
# => Ruby on Rails
|
|
201
|
+
def strip_links(text)
|
|
202
|
+
text.gsub(/<a\b.*?>(.*?)<\/a>/mi, '\1')
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
# Creates a Cycle object whose _to_s_ method cycles through elements of an
|
|
206
|
+
# array every time it is called. This can be used for example, to alternate
|
|
207
|
+
# classes for table rows:
|
|
208
|
+
#
|
|
209
|
+
# <% @items.each do |item| %>
|
|
210
|
+
# <tr class="<%= cycle("even", "odd") -%>">
|
|
211
|
+
# <td>item</td>
|
|
212
|
+
# </tr>
|
|
213
|
+
# <% end %>
|
|
214
|
+
#
|
|
215
|
+
# You can use named cycles to allow nesting in loops. Passing a Hash as
|
|
216
|
+
# the last parameter with a <tt>:name</tt> key will create a named cycle.
|
|
217
|
+
# You can manually reset a cycle by calling reset_cycle and passing the
|
|
218
|
+
# name of the cycle.
|
|
219
|
+
#
|
|
220
|
+
# <% @items.each do |item| %>
|
|
221
|
+
# <tr class="<%= cycle("even", "odd", :name => "row_class")
|
|
222
|
+
# <td>
|
|
223
|
+
# <% item.values.each do |value| %>
|
|
224
|
+
# <span style="color:<%= cycle("red", "green", "blue", :name => "colors") -%>">
|
|
225
|
+
# value
|
|
226
|
+
# </span>
|
|
227
|
+
# <% end %>
|
|
228
|
+
# <% reset_cycle("colors") %>
|
|
229
|
+
# </td>
|
|
230
|
+
# </tr>
|
|
231
|
+
# <% end %>
|
|
232
|
+
def cycle(first_value, *values)
|
|
233
|
+
if (values.last.instance_of? Hash)
|
|
234
|
+
params = values.pop
|
|
235
|
+
name = params[:name]
|
|
236
|
+
else
|
|
237
|
+
name = "default"
|
|
238
|
+
end
|
|
239
|
+
values.unshift(first_value)
|
|
240
|
+
|
|
241
|
+
cycle = get_cycle(name)
|
|
242
|
+
if (cycle.nil? || cycle.values != values)
|
|
243
|
+
cycle = set_cycle(name, Cycle.new(*values))
|
|
244
|
+
end
|
|
245
|
+
return cycle.to_s
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
# Resets a cycle so that it starts from the first element the next time
|
|
249
|
+
# it is called. Pass in +name+ to reset a named cycle.
|
|
250
|
+
def reset_cycle(name = "default")
|
|
251
|
+
cycle = get_cycle(name)
|
|
252
|
+
cycle.reset unless cycle.nil?
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
class Cycle #:nodoc:
|
|
256
|
+
attr_reader :values
|
|
257
|
+
|
|
258
|
+
def initialize(first_value, *values)
|
|
259
|
+
@values = values.unshift(first_value)
|
|
260
|
+
reset
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
def reset
|
|
264
|
+
@index = 0
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
def to_s
|
|
268
|
+
value = @values[@index].to_s
|
|
269
|
+
@index = (@index + 1) % @values.size
|
|
270
|
+
return value
|
|
271
|
+
end
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
private
|
|
275
|
+
# The cycle helpers need to store the cycles in a place that is
|
|
276
|
+
# guaranteed to be reset every time a page is rendered, so it
|
|
277
|
+
# uses an instance variable of ActionView::Base.
|
|
278
|
+
def get_cycle(name)
|
|
279
|
+
@_cycles = Hash.new unless defined?(@_cycles)
|
|
280
|
+
return @_cycles[name]
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
def set_cycle(name, cycle_object)
|
|
284
|
+
@_cycles = Hash.new unless defined?(@_cycles)
|
|
285
|
+
@_cycles[name] = cycle_object
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
AUTO_LINK_RE = %r{
|
|
289
|
+
( # leading text
|
|
290
|
+
<\w+.*?>| # leading HTML tag, or
|
|
291
|
+
[^=!:'"/]| # leading punctuation, or
|
|
292
|
+
^ # beginning of line
|
|
293
|
+
)
|
|
294
|
+
(
|
|
295
|
+
(?:https?://)| # protocol spec, or
|
|
296
|
+
(?:www\.) # www.*
|
|
297
|
+
)
|
|
298
|
+
(
|
|
299
|
+
[-\w]+ # subdomain or domain
|
|
300
|
+
(?:\.[-\w]+)* # remaining subdomains or domain
|
|
301
|
+
(?::\d+)? # port
|
|
302
|
+
(?:/(?:(?:[~\w\+%-]|(?:[,.;:][^\s$]))+)?)* # path
|
|
303
|
+
(?:\?[\w\+%&=.;-]+)? # query string
|
|
304
|
+
(?:\#[\w\-]*)? # trailing anchor
|
|
305
|
+
)
|
|
306
|
+
([[:punct:]]|\s|<|$) # trailing text
|
|
307
|
+
}x unless const_defined?(:AUTO_LINK_RE)
|
|
308
|
+
|
|
309
|
+
# Turns all urls into clickable links. If a block is given, each url
|
|
310
|
+
# is yielded and the result is used as the link text.
|
|
311
|
+
def auto_link_urls(text, href_options = {})
|
|
312
|
+
extra_options = tag_options(href_options.stringify_keys) || ""
|
|
313
|
+
text.gsub(AUTO_LINK_RE) do
|
|
314
|
+
all, a, b, c, d = $&, $1, $2, $3, $4
|
|
315
|
+
if a =~ /<a\s/i # don't replace URL's that are already linked
|
|
316
|
+
all
|
|
317
|
+
else
|
|
318
|
+
text = b + c
|
|
319
|
+
text = yield(text) if block_given?
|
|
320
|
+
%(#{a}<a href="#{b=="www."?"http://www.":b}#{c}"#{extra_options}>#{text}</a>#{d})
|
|
321
|
+
end
|
|
322
|
+
end
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
# Turns all email addresses into clickable links. If a block is given,
|
|
326
|
+
# each email is yielded and the result is used as the link text.
|
|
327
|
+
def auto_link_email_addresses(text)
|
|
328
|
+
text.gsub(/([\w\.!#\$%\-+.]+@[A-Za-z0-9\-]+(\.[A-Za-z0-9\-]+)+)/) do
|
|
329
|
+
text = $1
|
|
330
|
+
text = yield(text) if block_given?
|
|
331
|
+
%{<a href="mailto:#{$1}">#{text}</a>}
|
|
332
|
+
end
|
|
333
|
+
end
|
|
334
|
+
end
|
|
335
|
+
end
|
|
336
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# This utility module will use jsdoc to create documentation from a SproutCore
|
|
2
|
+
# client. Note that for this to work you must have Java installed (sudder).
|
|
3
|
+
module SproutCore
|
|
4
|
+
|
|
5
|
+
module JSDoc
|
|
6
|
+
|
|
7
|
+
# Creates the documentation for the specified set of clients, replacing
|
|
8
|
+
# the contents of the output file. Requires some of the following
|
|
9
|
+
# options.
|
|
10
|
+
#
|
|
11
|
+
# :bundle => A Bundle instance - or -
|
|
12
|
+
# :files => Absolute paths to input files
|
|
13
|
+
# :build_path => absolute path to the build root. Uses the bundle if not provided.
|
|
14
|
+
def self.generate(opts = {})
|
|
15
|
+
bundle = opts[:bundle]
|
|
16
|
+
build_path = opts[:build_path] || File.join(bundle.build_root, '-docs', 'data')
|
|
17
|
+
raise "MISSING OPTION: :bundle => bundle or :build_path => path required for JSDoc" if build_path.nil?
|
|
18
|
+
|
|
19
|
+
# get the list of files to build for.
|
|
20
|
+
files = opts[:files]
|
|
21
|
+
if files.nil?
|
|
22
|
+
raise "MISSING OPTION: :bundle => bundle or :files => list of files required for JSDoc" if bundle.nil?
|
|
23
|
+
entries = bundle.entries_for(:javascript, :hidden => :include)
|
|
24
|
+
files = entries.map { |x| x.composite? ? nil : x.source_path }.compact.uniq
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Ensure directory exists
|
|
28
|
+
FileUtils.mkdir_p(build_path)
|
|
29
|
+
|
|
30
|
+
# Now run jsdoc
|
|
31
|
+
jsdoc_root = File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'jsdoc'))
|
|
32
|
+
jar_path = File.join(jsdoc_root, 'app', 'js.jar')
|
|
33
|
+
runjs_path = File.join(jsdoc_root, 'app', 'run.js')
|
|
34
|
+
template_path = File.join(jsdoc_root, 'templates', 'sproutcore')
|
|
35
|
+
|
|
36
|
+
SC.logger.debug `java -Djsdoc.dir=#{jsdoc_root} -jar #{jar_path} #{runjs_path} -t=#{template_path} -d=#{build_path} #{files * ' '} -v`
|
|
37
|
+
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|