Skip to content
Browse files

Setup of GS Application with Jasmine + ConsoleReporter

  • Loading branch information...
0 parents commit 32f6e73a739ac4df5facd8964ef6451d8dbe3143 @ericchaves committed Mar 21, 2012
Showing with 34,489 additions and 0 deletions.
  1. +28 −0 .gitignore
  2. +1 −0 .senchasdk
  3. +47 −0 app.js
  4. +112 −0 app.json
  5. +47 −0 app/view/Main.js
  6. +84 −0 index.html
  7. +126 −0 packager.json
  8. +6,755 −0 resources/css/app.css
  9. BIN resources/loading/Default-LandscapeLeft~ipad.png
  10. BIN resources/loading/Default-LandscapeRight~ipad.png
  11. BIN resources/loading/Default-Landscape~ipad.png
  12. BIN resources/loading/Default-PortraitUpsideDown~ipad.png
  13. BIN resources/loading/Default-Portrait~ipad.png
  14. BIN resources/loading/Default.png
  15. BIN resources/loading/Default@2x.png
  16. BIN resources/loading/Default~ipad.png
  17. BIN resources/loading/Homescreen.jpg
  18. BIN resources/loading/Homescreen~ipad.jpg
  19. +19 −0 resources/sass/app.scss
  20. +14 −0 resources/sass/config.rb
  21. +9 −0 sdk/command/bin/sencha
  22. +10 −0 sdk/command/bin/sencha.bat
  23. +4 −0 sdk/command/sencha
  24. +14 −0 sdk/command/sencha.bat
  25. +57 −0 sdk/command/sencha.js
  26. +4 −0 sdk/command/senchadebug
  27. +300 −0 sdk/command/src/Cli.js
  28. +179 −0 sdk/command/src/Preprocessor.js
  29. +53 −0 sdk/command/src/log/formatter/Cli.js
  30. +7 −0 sdk/command/src/log/writer/Cli.js
  31. +67 −0 sdk/command/src/module/Abstract.js
  32. +316 −0 sdk/command/src/module/Application.js
  33. +297 −0 sdk/command/src/module/FileSystem.js
  34. +71 −0 sdk/command/src/module/Generate.js
  35. +156 −0 sdk/command/src/module/Manifest.js
  36. +61 −0 sdk/command/src/module/Package.js
  37. +82 −0 sdk/command/src/module/Project.js
  38. +22 −0 sdk/command/src/module/Test.js
  39. +68 −0 sdk/command/src/module/generate/App.js
  40. +1 −0 sdk/command/src/module/generate/App/.senchasdk.tpl
  41. +43 −0 sdk/command/src/module/generate/App/app.js.tpl
  42. +112 −0 sdk/command/src/module/generate/App/app.json.tpl
  43. +47 −0 sdk/command/src/module/generate/App/app/view/Main.js.tpl
  44. +76 −0 sdk/command/src/module/generate/App/index.html.tpl
  45. +126 −0 sdk/command/src/module/generate/App/packager.json.tpl
  46. BIN sdk/command/src/module/generate/App/resources/loading/Default-LandscapeLeft~ipad.png
  47. BIN sdk/command/src/module/generate/App/resources/loading/Default-LandscapeRight~ipad.png
  48. BIN sdk/command/src/module/generate/App/resources/loading/Default-Landscape~ipad.png
  49. BIN sdk/command/src/module/generate/App/resources/loading/Default-PortraitUpsideDown~ipad.png
  50. BIN sdk/command/src/module/generate/App/resources/loading/Default-Portrait~ipad.png
  51. BIN sdk/command/src/module/generate/App/resources/loading/Default.png
  52. BIN sdk/command/src/module/generate/App/resources/loading/Default@2x.png
  53. BIN sdk/command/src/module/generate/App/resources/loading/Default~ipad.png
  54. BIN sdk/command/src/module/generate/App/resources/loading/Homescreen.jpg
  55. BIN sdk/command/src/module/generate/App/resources/loading/Homescreen~ipad.jpg
  56. +19 −0 sdk/command/src/module/generate/App/resources/sass/app.scss.tpl
  57. +14 −0 sdk/command/src/module/generate/App/resources/sass/config.rb.tpl
  58. +21 −0 sdk/command/src/module/generate/Controller.js
  59. +17 −0 sdk/command/src/module/generate/Controller/controller.js.tpl
  60. +36 −0 sdk/command/src/module/generate/Form.js
  61. +21 −0 sdk/command/src/module/generate/Form/form.js.tpl
  62. +106 −0 sdk/command/src/module/generate/Generator.js
  63. +45 −0 sdk/command/src/module/generate/Model.js
  64. +9 −0 sdk/command/src/module/generate/Model/model.js.tpl
  65. +21 −0 sdk/command/src/module/generate/Profile.js
  66. +16 −0 sdk/command/src/module/generate/Profile/profile.js.tpl
  67. +30 −0 sdk/command/src/preprocessor/LineStack.js
  68. +121 −0 sdk/command/src/preprocessor/Statement.js
  69. +38 −0 sdk/command/src/preprocessor/statement/Debug.js
  70. +36 −0 sdk/command/src/preprocessor/statement/Deprecated.js
  71. +18 −0 sdk/command/src/preprocessor/statement/Else.js
  72. +28 −0 sdk/command/src/preprocessor/statement/Elseif.js
  73. +20 −0 sdk/command/src/preprocessor/statement/Feature.js
  74. +69 −0 sdk/command/src/preprocessor/statement/If.js
  75. +20 −0 sdk/command/templates/action.tpl
  76. +19 −0 sdk/command/templates/actions.tpl
  77. +9 −0 sdk/command/templates/cache.manifest.tpl
  78. +24 −0 sdk/command/templates/modules.tpl
  79. +92 −0 sdk/command/test/unit/specs/PreprocessorSpec.js
  80. +9 −0 sdk/command/test/unit/specs/SampleSpec.js
  81. +14 −0 sdk/command/test/unit/specs/preprocessor/statement/IfSpec.js
  82. +202 −0 sdk/command/vendor/closurecompiler/COPYING
  83. +292 −0 sdk/command/vendor/closurecompiler/README
  84. +86 −0 sdk/command/vendor/nodejs/LICENSE
  85. +7 −0 sdk/command/vendor/nodejs/node_modules/.bin/jasmine-node
  86. +323 −0 sdk/command/vendor/nodejs/node_modules/.bin/uglifyjs
  87. +101 −0 sdk/command/vendor/nodejs/node_modules/findit/README.markdown
  88. +3 −0 sdk/command/vendor/nodejs/node_modules/findit/examples/callback.js
  89. +9 −0 sdk/command/vendor/nodejs/node_modules/findit/examples/emitter.js
  90. +2 −0 sdk/command/vendor/nodejs/node_modules/findit/examples/sync.js
  91. +142 −0 sdk/command/vendor/nodejs/node_modules/findit/index.js
  92. +1 −0 sdk/command/vendor/nodejs/node_modules/findit/node_modules/seq/.npmignore
  93. +442 −0 sdk/command/vendor/nodejs/node_modules/findit/node_modules/seq/README.markdown
  94. +18 −0 sdk/command/vendor/nodejs/node_modules/findit/node_modules/seq/examples/join.js
  95. +12 −0 sdk/command/vendor/nodejs/node_modules/findit/node_modules/seq/examples/parseq.coffee
  96. +19 −0 sdk/command/vendor/nodejs/node_modules/findit/node_modules/seq/examples/parseq.js
  97. +16 −0 sdk/command/vendor/nodejs/node_modules/findit/node_modules/seq/examples/stat_all.coffee
  98. +17 −0 sdk/command/vendor/nodejs/node_modules/findit/node_modules/seq/examples/stat_all.js
  99. +520 −0 sdk/command/vendor/nodejs/node_modules/findit/node_modules/seq/index.js
  100. +1 −0 sdk/command/vendor/nodejs/node_modules/findit/node_modules/seq/node_modules/chainsaw/.npmignore
  101. +140 −0 sdk/command/vendor/nodejs/node_modules/findit/node_modules/seq/node_modules/chainsaw/README.markdown
  102. +25 −0 ...mmand/vendor/nodejs/node_modules/findit/node_modules/seq/node_modules/chainsaw/examples/add_do.js
  103. +67 −0 ...mmand/vendor/nodejs/node_modules/findit/node_modules/seq/node_modules/chainsaw/examples/prompt.js
  104. +108 −0 sdk/command/vendor/nodejs/node_modules/findit/node_modules/seq/node_modules/chainsaw/index.js
  105. +1 −0 ...odejs/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/.npmignore
  106. +24 −0 ...r/nodejs/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/LICENSE
  107. +247 −0 .../node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/README.markdown
  108. +16 −0 ...node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/examples/json.js
  109. +15 −0 ...de_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/examples/leaves.js
  110. +8 −0 ..._modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/examples/negative.js
  111. +38 −0 ...modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/examples/stringify.js
  112. +322 −0 .../nodejs/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/index.js
  113. +18 −0 ...ejs/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/package.json
  114. +114 −0 ...node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/test/circular.js
  115. +35 −0 ...ejs/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/test/date.js
  116. +219 −0 ...js/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/test/equal.js
  117. +17 −0 ...node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/test/instance.js
  118. +42 −0 ...ode_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/test/interface.js
  119. +47 −0 ...ejs/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/test/json.js
  120. +21 −0 ...s/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/test/leaves.js
  121. +203 −0 ...de_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/test/mutability.js
  122. +20 −0 ...node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/test/negative.js
  123. +15 −0 ...dejs/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/test/obj.js
  124. +41 −0 ...ejs/node_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/test/stop.js
  125. +36 −0 ...ode_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/test/stringify.js
  126. +54 −0 ...de_modules/findit/node_modules/seq/node_modules/chainsaw/node_modules/traverse/test/super_deep.js
  127. +23 −0 sdk/command/vendor/nodejs/node_modules/findit/node_modules/seq/node_modules/chainsaw/package.json
  128. +418 −0 ...command/vendor/nodejs/node_modules/findit/node_modules/seq/node_modules/chainsaw/test/chainsaw.js
  129. +191 −0 sdk/command/vendor/nodejs/node_modules/findit/node_modules/seq/node_modules/hashish/README.markdown
  130. +9 −0 ...command/vendor/nodejs/node_modules/findit/node_modules/seq/node_modules/hashish/examples/chain.js
  131. +7 −0 sdk/command/vendor/nodejs/node_modules/findit/node_modules/seq/node_modules/hashish/examples/map.js
  132. +253 −0 sdk/command/vendor/nodejs/node_modules/findit/node_modules/seq/node_modules/hashish/index.js
  133. +1 −0 ...nodejs/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/.npmignore
  134. +24 −0 ...or/nodejs/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/LICENSE
  135. +256 −0 ...s/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/README.markdown
  136. +16 −0 .../node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/examples/json.js
  137. +15 −0 ...ode_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/examples/leaves.js
  138. +8 −0 ...e_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/examples/negative.js
  139. +10 −0 ...node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/examples/scrub.js
  140. +38 −0 ..._modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/examples/stringify.js
  141. +279 −0 ...r/nodejs/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/index.js
  142. +18 −0 ...dejs/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/package.json
  143. +115 −0 .../node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/test/circular.js
  144. +35 −0 ...dejs/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/test/date.js
  145. +220 −0 ...ejs/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/test/equal.js
  146. +13 −0 ...odejs/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/test/has.js
  147. +17 −0 .../node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/test/instance.js
  148. +42 −0 ...node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/test/interface.js
  149. +47 −0 ...dejs/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/test/json.js
  150. +29 −0 ...dejs/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/test/keys.js
  151. +21 −0 ...js/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/test/leaves.js
  152. +92 −0 ...modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/test/lib/deep_equal.js
  153. +252 −0 ...ode_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/test/mutability.js
  154. +20 −0 .../node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/test/negative.js
  155. +15 −0 ...odejs/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/test/obj.js
  156. +35 −0 .../node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/test/siblings.js
  157. +41 −0 ...dejs/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/test/stop.js
  158. +36 −0 ...node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/test/stringify.js
  159. +34 −0 ...s/node_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/test/subexpr.js
  160. +55 −0 ...ode_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/test/super_deep.js
  161. +22 −0 ...ode_modules/findit/node_modules/seq/node_modules/hashish/node_modules/traverse/testling/leaves.js
  162. +33 −0 sdk/command/vendor/nodejs/node_modules/findit/node_modules/seq/node_modules/hashish/package.json
  163. +250 −0 sdk/command/vendor/nodejs/node_modules/findit/node_modules/seq/node_modules/hashish/test/hash.js
  164. +69 −0 sdk/command/vendor/nodejs/node_modules/findit/node_modules/seq/node_modules/hashish/test/property.js
  165. +33 −0 sdk/command/vendor/nodejs/node_modules/findit/node_modules/seq/package.json
  166. +35 −0 sdk/command/vendor/nodejs/node_modules/findit/node_modules/seq/test/readdir.js
  167. +946 −0 sdk/command/vendor/nodejs/node_modules/findit/node_modules/seq/test/seq.js
  168. +149 −0 sdk/command/vendor/nodejs/node_modules/findit/node_modules/seq/test/seq_.js
  169. +34 −0 sdk/command/vendor/nodejs/node_modules/findit/package.json
  170. +142 −0 sdk/command/vendor/nodejs/node_modules/jasmine-node.js
  171. +12 −0 sdk/command/vendor/nodejs/node_modules/jasmine-node/.npmignore
  172. +22 −0 sdk/command/vendor/nodejs/node_modules/jasmine-node/LICENSE
  173. +56 −0 sdk/command/vendor/nodejs/node_modules/jasmine-node/README.md
  174. +7 −0 sdk/command/vendor/nodejs/node_modules/jasmine-node/bin/jasmine-node
  175. +41 −0 sdk/command/vendor/nodejs/node_modules/jasmine-node/lib/jasmine-node/async-callback.js
  176. +86 −0 sdk/command/vendor/nodejs/node_modules/jasmine-node/lib/jasmine-node/autotest.js
  177. +174 −0 sdk/command/vendor/nodejs/node_modules/jasmine-node/lib/jasmine-node/cli.js
  178. +145 −0 sdk/command/vendor/nodejs/node_modules/jasmine-node/lib/jasmine-node/index.js
  179. +2,479 −0 sdk/command/vendor/nodejs/node_modules/jasmine-node/lib/jasmine-node/jasmine-2.0.0.rc1.js
  180. +275 −0 sdk/command/vendor/nodejs/node_modules/jasmine-node/lib/jasmine-node/reporter.js
  181. +70 −0 sdk/command/vendor/nodejs/node_modules/jasmine-node/lib/jasmine-node/requirejs-runner.js
  182. +48 −0 sdk/command/vendor/nodejs/node_modules/jasmine-node/lib/jasmine-node/requirejs-spec-loader.js
  183. +65 −0 sdk/command/vendor/nodejs/node_modules/jasmine-node/lib/jasmine-node/requirejs-wrapper-template.js
  184. +36 −0 sdk/command/vendor/nodejs/node_modules/jasmine-node/lib/jasmine-node/spec-collection.js
  185. +7 −0 sdk/command/vendor/nodejs/node_modules/jasmine-node/node_modules/.bin/cake
  186. +7 −0 sdk/command/vendor/nodejs/node_modules/jasmine-node/node_modules/.bin/coffee
  187. +9,823 −0 sdk/command/vendor/nodejs/node_modules/jasmine-node/node_modules/.bin/r.js
  188. +11 −0 sdk/command/vendor/nodejs/node_modules/jasmine-node/node_modules/coffee-script/.npmignore
  189. +22 −0 sdk/command/vendor/nodejs/node_modules/jasmine-node/node_modules/coffee-script/LICENSE
  190. +51 −0 sdk/command/vendor/nodejs/node_modules/jasmine-node/node_modules/coffee-script/README
  191. +78 −0 sdk/command/vendor/nodejs/node_modules/jasmine-node/node_modules/coffee-script/Rakefile
  192. +7 −0 sdk/command/vendor/nodejs/node_modules/jasmine-node/node_modules/coffee-script/bin/cake
  193. +7 −0 sdk/command/vendor/nodejs/node_modules/jasmine-node/node_modules/coffee-script/bin/coffee
  194. +44 −0 sdk/command/vendor/nodejs/node_modules/jasmine-node/node_modules/coffee-script/extras/jsl.conf
  195. +74 −0 ...d/vendor/nodejs/node_modules/jasmine-node/node_modules/coffee-script/lib/coffee-script/browser.js
  196. +99 −0 ...mand/vendor/nodejs/node_modules/jasmine-node/node_modules/coffee-script/lib/coffee-script/cake.js
  197. +150 −0 ...or/nodejs/node_modules/jasmine-node/node_modules/coffee-script/lib/coffee-script/coffee-script.js
  198. +442 −0 ...d/vendor/nodejs/node_modules/jasmine-node/node_modules/coffee-script/lib/coffee-script/command.js
  199. +592 −0 ...d/vendor/nodejs/node_modules/jasmine-node/node_modules/coffee-script/lib/coffee-script/grammar.js
  200. +72 −0 ...d/vendor/nodejs/node_modules/jasmine-node/node_modules/coffee-script/lib/coffee-script/helpers.js
  201. +10 −0 ...and/vendor/nodejs/node_modules/jasmine-node/node_modules/coffee-script/lib/coffee-script/index.js
  202. +686 −0 ...and/vendor/nodejs/node_modules/jasmine-node/node_modules/coffee-script/lib/coffee-script/lexer.js
Sorry, we could not display the entire diff because too many files (1,236) changed.
28 .gitignore
@@ -0,0 +1,28 @@
+.DS_Store
+
+# Thumbnails
+._*
+
+# Files that might appear on external disk
+.Spotlight-V100
+.Trashes
+
+# Exclude the build directory
+build/*
+
+# Exclude temp nibs and swap files
+*~.nib
+*.swp
+
+# Exclude OS X folder attributes
+.DS_Store
+
+# Exclude user-specific XCode 3 and 4 files
+*.mode1
+*.mode1v3
+*.mode2v3
+*.perspective
+*.perspectivev3
+*.pbxuser
+*.xcworkspace
+xcuserdata
1 .senchasdk
@@ -0,0 +1 @@
+sdk
47 app.js
@@ -0,0 +1,47 @@
+//<debug>
+Ext.Loader.setPath({
+ 'Ext': 'sdk/src'
+});
+//</debug>
+
+Ext.application({
+ name: 'GS',
+
+ requires: [
+ 'Ext.MessageBox'
+ ],
+
+ views: ['Main'],
+
+ icon: {
+ 57: 'resources/icons/Icon.png',
+ 72: 'resources/icons/Icon~ipad.png',
+ 114: 'resources/icons/Icon@2x.png',
+ 144: 'resources/icons/Icon~ipad@2x.png'
+ },
+
+ phoneStartupScreen: 'resources/loading/Homescreen.jpg',
+ tabletStartupScreen: 'resources/loading/Homescreen~ipad.jpg',
+
+ launch: function() {
+ // Destroy the #appLoadingIndicator element
+ Ext.fly('appLoadingIndicator').destroy();
+
+ // Initialize the main view
+ Ext.Viewport.add(Ext.create('GS.view.Main'));
+
+ // Execute jasmine tests
+ jasmine.getEnv().addReporter(new jasmine.ConsoleReporter());
+ jasmine.getEnv().execute();
+ },
+
+ onUpdated: function() {
+ Ext.Msg.confirm(
+ "Application Update",
+ "This application has just successfully been updated to the latest version. Reload now?",
+ function() {
+ window.location.reload();
+ }
+ );
+ }
+});
112 app.json
@@ -0,0 +1,112 @@
+{
+ /**
+ * The application's namespace, used by Sencha Command to generate classes
+ */
+ "name": "GS",
+
+ /**
+ * List of all JavaScript assets in the right execution order.
+ * Each item is an object with the following format:
+ * {
+ * "path": "path/to/script.js" // Relative path to this app.json file
+ * "update": "delta" // (Optional)
+ * // - If not specified, this file will only be loaded once, and
+ * // cached inside localStorage until this value is changed.
+ * // - "delta" to enable over-the-air delta update for this file
+ * // - "full" means full update will be made when this file changes
+ *
+ * }
+ */
+ "js": [
+ {
+ "path": "sdk/sencha-touch.js"
+ },
+ {
+ "path": "app.js",
+ "update": "delta"
+ }
+ ],
+
+ /**
+ * List of all CSS assets in the right inclusion order.
+ * Each item is an object with the following format:
+ * {
+ * "path": "path/to/item.css" // Relative path to this app.json file
+ * "update": "delta" // (Optional)
+ * // - If not specified, this file will only be loaded once, and
+ * // cached inside localStorage until this value is changed to either one below
+ * // - "delta" to enable over-the-air delta update for this file
+ * // - "full" means full update will be made when this file changes
+ *
+ * }
+ */
+ "css": [
+ {
+ "path": "resources/css/app.css",
+ "update": "delta"
+ }
+ ],
+
+ /**
+ * Used to automatically generate cache.manifest (HTML 5 application cache manifest) file when you build
+ */
+ "appCache": {
+ /**
+ * List of items in the CACHE MANIFEST section
+ */
+ "cache": [
+ "index.html"
+ ],
+ /**
+ * List of items in the NETWORK section
+ */
+ "network": [
+ "*"
+ ],
+ /**
+ * List of items in the FALLBACK section
+ */
+ "fallback": []
+ },
+
+ /**
+ * Extra resources to be copied along when build
+ */
+ "extras": [
+ "resources/images",
+ "resources/icons",
+ "resources/loading"
+ ],
+
+ /**
+ * Directory path to store all previous production builds. Note that the content generated inside this directory
+ * must be kept intact for proper generation of delta between updates
+ */
+ "archivePath": "archive",
+
+ /**
+ * Default paths to build this application to for each environment
+ */
+ "buildPaths": {
+ "testing": "build/testing",
+ "production": "build/production",
+ "package": "build/package",
+ "native": "build/native"
+ },
+
+ /**
+ * Build options
+ */
+ "buildOptions": {
+ "product": "touch",
+ "minVersion": 3,
+ "debug": false,
+ "logger": "no"
+ },
+
+ /**
+ * Uniquely generated id for this application, used as prefix for localStorage keys.
+ * Normally you should never change this value.
+ */
+ "id": "ca829310-736d-11e1-8480-4145800ed8d8"
+}
47 app/view/Main.js
@@ -0,0 +1,47 @@
+Ext.define("GS.view.Main", {
+ extend: 'Ext.tab.Panel',
+ requires: ['Ext.TitleBar'],
+
+ config: {
+ tabBarPosition: 'bottom',
+
+ items: [
+ {
+ title: 'Welcome',
+ iconCls: 'home',
+
+ styleHtmlContent: true,
+ scrollable: true,
+
+ items: {
+ docked: 'top',
+ xtype: 'titlebar',
+ title: 'Welcome to Sencha Touch 2'
+ },
+
+ html: [
+ "You've just generated a new Sencha Touch 2 project. What you're looking at right now is the ",
+ "contents of <a target='_blank' href=\"app/view/Main.js\">app/view/Main.js</a> - edit that file ",
+ "and refresh to change what's rendered here."
+ ].join("")
+ },
+ {
+ title: 'Get Started',
+ iconCls: 'action',
+
+ items: [
+ {
+ docked: 'top',
+ xtype: 'titlebar',
+ title: 'Getting Started'
+ },
+ {
+ xtype: 'video',
+ url: 'http://av.vimeo.com/64284/137/87347327.mp4?token=1330978144_f9b698fea38cd408d52a2393240c896c',
+ posterUrl: 'http://b.vimeocdn.com/ts/261/062/261062119_640.jpg'
+ }
+ ]
+ }
+ ]
+ }
+});
84 index.html
@@ -0,0 +1,84 @@
+<!DOCTYPE HTML>
+<html manifest="" lang="en-US">
+<head>
+ <meta charset="UTF-8">
+ <title>GS</title>
+ <style type="text/css">
+ /**
+ * Example of an initial loading indicator.
+ * It is recommended to keep this as minimal as possible to provide instant feedback
+ * while other resources are still being loaded for the first time
+ */
+ html, body {
+ height: 100%;
+ }
+
+ #appLoadingIndicator {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ margin-top: -10px;
+ margin-left: -50px;
+ width: 100px;
+ height: 20px;
+ }
+
+ #appLoadingIndicator > * {
+ background-color: #FFFFFF;
+ float: left;
+ height: 20px;
+ margin-left: 11px;
+ width: 20px;
+ -webkit-animation-name: appLoadingIndicator;
+ -webkit-border-radius: 13px;
+ -webkit-animation-duration: 0.8s;
+ -webkit-animation-iteration-count: infinite;
+ -webkit-animation-direction: linear;
+ opacity: 0.3
+ }
+
+ #appLoadingIndicator > :nth-child(1) {
+ -webkit-animation-delay: 0.18s;
+ }
+
+ #appLoadingIndicator > :nth-child(2) {
+ -webkit-animation-delay: 0.42s;
+ }
+
+ #appLoadingIndicator > :nth-child(3) {
+ -webkit-animation-delay: 0.54s;
+ }
+
+ @-webkit-keyframes appLoadingIndicator{
+ 0% {
+ opacity: 0.3
+ }
+
+ 50% {
+ opacity: 1;
+ background-color:#1985D0
+ }
+
+ 100% {
+ opacity:0.3
+ }
+ }
+ </style>
+ <!-- Jasmine Test Framework -->
+ <link rel="stylesheet" href="tests/jasmine-standalone-1.1.0/lib/jasmine-1.1.0/jasmine.css" type="text/css"/>
+ <script type="text/javascript" src="tests/jasmine-standalone-1.1.0/lib/jasmine-1.1.0/jasmine.js"></script>
+ <script type="text/javascript" src="tests/jasmine-standalone-1.1.0/lib/jasmine-1.1.0/jasmine-html.js"></script>
+ <script type="text/javascript" src="tests/reporters/jasmine.console_reporter.js"></script>
+ <!-- Sencha Touch2 microloader -->
+ <script id="microloader" type="text/javascript" src="sdk/microloader/development.js"></script>
+ <!-- Specs -->
+ <script type="text/javascript" src="tests/spec/Sample.spec.js"></script>
+</head>
+<body>
+ <div id="appLoadingIndicator">
+ <div></div>
+ <div></div>
+ <div></div>
+ </div>
+</body>
+</html>
126 packager.json
@@ -0,0 +1,126 @@
+{
+ /**
+ * @cfg {String} applicationName
+ * @required
+ * This is the name of your application, which is displayed on the device when the app is installed. On IOS, this should match
+ * the name of your application in the Apple Provisioning Portal.
+ */
+ "applicationName":"My Application",
+
+ /**
+ * @cfg {String} applicationId
+ * This is the name namespace for your application. On IOS, this should match the name of your application in the Apple Provisioning Portal.
+ */
+ "applicationId":"com.mycompany.myAppID",
+
+ /**
+ * @cfg {String} versionString
+ * @required
+ * This is the version of your application.
+ */
+ "versionString":"1.0",
+
+ /**
+ * @cfg {String} iconName
+ * This is file name of your icon. This should be in the same directory of this configuration file.
+ *
+ * For iOS, please refer to their documentation about icon sizes:
+ * https://developer.apple.com/library/ios/#documentation/userexperience/conceptual/mobilehig/IconsImages/IconsImages.html
+ *
+ * For Android, please refer to the Google Launcher icons guide:
+ * http://developer.android.com/guide/practices/ui_guidelines/icon_design_launcher.html
+ */
+ "iconName":"resources/icons/Icon~ipad.png",
+
+ /**
+ * @cfg {String} inputPath
+ * @required
+ * This is location of your Sencha Touch 2 application, relative to this configuration file.
+ */
+ "inputPath":"build/native",
+
+ /**
+ * @cfg {String} outputPath
+ * @required
+ * This is where the built application file with be saved.
+ */
+ "outputPath":"build/",
+
+ /**
+ * @cfg {String} configuration
+ * @required
+ * This is configuration for your application. `Debug` should always be used unless you are submitting your app to an online
+ * store - in which case `Release` should be specified.
+ */
+ "configuration":"Debug",
+
+ /**
+ * @cfg {String} platform
+ * @required
+ * This is the platform where you will be running your application. Available options are:
+ * - iOSSimulator
+ * - iOS
+ * - Android
+ * - AndroidEmulator
+ */
+ "platform":"iOSSimulator",
+
+ /**
+ * @cfg {String} deviceType
+ * @required
+ * This is device type that your application will be running on.
+ *
+ * If you are developing for Android, this is not necessary.
+ *
+ * Available options are:
+ * - iPhone
+ * - iPad
+ * - Universal
+ */
+ "deviceType":"Universal",
+
+ /**
+ * @cfg {String} certificatePath
+ * This is the location of your certificate.
+ * This is required when you are developing for Android or you are developing on Windows.
+ */
+ "certificatePath":"/path/to/certificate.file",
+
+ /**
+ * @cfg {String} certificateAlias
+ * This is the name of your certificate.
+ *
+ * IF you do not specify this on OSX, we will try and automatically find the certificate for you using the applicationId.
+ *
+ * This can be just a simple matcher. For example, if your certificate name is "iPhone Developer: Robert Dougan (ABCDEFGHIJ)", you
+ * can just put "iPhone Developer".
+ *
+ * When using a certificatePath on Windows, you do not need to specify this.
+ */
+ "certificateAlias":"",
+
+ /**
+ * @cfg {String} sdkPath
+ * This is the path to the Android SDK, if you are developing an Android application.
+ */
+ "sdkPath":"/path/to/android-sdk",
+
+ /**
+ * @cfg androidAPILevel
+ * This is android API level, the version of Android SDK to use, you can read more about it here: http://developer.android.com/guide/appendix/api-levels.html.
+ * Be sure to install corresponding platform API in android SDK manager (android_sdk/tools/android)
+ */
+ "androidAPILevel":"15",
+
+ /**
+ * @cfg orientations
+ * @required
+ * This is orientations that this application can run.
+ */
+ "orientations": [
+ "portrait",
+ "landscapeLeft",
+ "landscapeRight",
+ "portraitUpsideDown"
+ ]
+}
6,755 resources/css/app.css
6,755 additions, 0 deletions not shown because the diff is too large. Please use a local Git client to view these changes.
BIN resources/loading/Default-LandscapeLeft~ipad.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN resources/loading/Default-LandscapeRight~ipad.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN resources/loading/Default-Landscape~ipad.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN resources/loading/Default-PortraitUpsideDown~ipad.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN resources/loading/Default-Portrait~ipad.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN resources/loading/Default.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN resources/loading/Default@2x.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN resources/loading/Default~ipad.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN resources/loading/Homescreen.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN resources/loading/Homescreen~ipad.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
19 resources/sass/app.scss
@@ -0,0 +1,19 @@
+@import 'sencha-touch/default/all';
+
+// You may remove any of the following modules that you
+// do not use in order to create a smaller css file.
+@include sencha-panel;
+@include sencha-buttons;
+@include sencha-sheet;
+@include sencha-picker;
+@include sencha-tabs;
+@include sencha-toolbar;
+@include sencha-toolbar-forms;
+@include sencha-indexbar;
+@include sencha-list;
+@include sencha-layout;
+@include sencha-carousel;
+@include sencha-form;
+@include sencha-msgbox;
+
+// Your custom code goes here...
14 resources/sass/config.rb
@@ -0,0 +1,14 @@
+# Get the directory that this configuration file exists in
+dir = File.dirname(__FILE__)
+
+# Load the sencha-touch framework automatically.
+load File.join(dir, '..', '..', 'sdk', 'resources', 'themes')
+
+# Compass configurations
+sass_path = dir
+css_path = File.join(dir, "..", "css")
+
+# Require any additional compass plugins here.
+images_dir = File.join(dir, "..", "images")
+output_style = :compressed
+environment = :production
9 sdk/command/bin/sencha
@@ -0,0 +1,9 @@
+#!/bin/sh
+if test -e ".senchasdk"
+then
+ sdkpath=`cat .senchasdk`
+ $sdkpath/command/sencha $*
+else
+ DIR=$(dirname $(which $0))"/../command"
+ jsdb -path $DIR $DIR/sencha.js $*
+fi
10 sdk/command/bin/sencha.bat
@@ -0,0 +1,10 @@
+@echo off
+
+IF EXIST .senchasdk (
+ SET /P sdkpath= < .senchasdk
+
+ "%sdkpath%\command\sencha" %*
+) ELSE (
+ set dir=%~dp0
+ jsdb -path "%dir%..\command" "%dir%..\command\sencha.js" %*
+)
4 sdk/command/sencha
@@ -0,0 +1,4 @@
+#!/bin/sh
+DIR=$(dirname $(which $0))
+export NODE_PATH=$DIR/vendor/nodejs/node_modules
+$DIR/vendor/nodejs/osx/node $DIR/sencha.js $*
14 sdk/command/sencha.bat
@@ -0,0 +1,14 @@
+@echo off
+
+IF EXIST .\sdk\command\sencha (
+ set NODE_PATH=.\sdk\command\vendor\nodejs\node_modules
+ .\sdk\command\vendor\nodejs\win\node sdk\command\sencha.js %*
+) ELSE (
+ IF EXIST .\command\sencha (
+ set NODE_PATH=.\command\vendor\nodejs\node_modules
+ .\command\vendor\nodejs\win\node command\sencha.js %*
+ ) ELSE (
+ set dir=%~dp0
+ jsdb -path "%dir%..\command" "%dir%..\command\sencha.js" %*
+ )
+)
57 sdk/command/sencha.js
@@ -0,0 +1,57 @@
+(function() {
+ var coreFiles = [
+ "Ext.js",
+ "version/Version.js",
+ "lang/String.js",
+ "lang/Number.js",
+ "lang/Array.js",
+ "lang/Function.js",
+ "lang/Object.js",
+ "lang/Date.js",
+ "lang/JSON.js",
+ "class/Base.js",
+ "class/Class.js",
+ "class/ClassManager.js",
+ "class/Loader.js",
+ "lang/Error.js"
+ ],
+ path = require('path'),
+ currentPath = __dirname,
+ srcPath = path.resolve(currentPath, '../src'),
+ corePath = path.join(srcPath, 'core'),
+ command;
+
+ coreFiles.forEach(function(file) {
+ require(path.join(corePath, file));
+ });
+
+ Ext.Loader.setConfig({
+ enabled: true,
+ paths: {
+ Ext: srcPath,
+ Command: path.join(currentPath, 'src')
+ }
+ });
+
+ command = Ext.create('Command.Cli', {
+ version: '2.0.0',
+ currentPath: currentPath,
+ modules: {
+ 'app': 'Application',
+ 'fs': 'FileSystem',
+ 'manifest': 'Manifest',
+ 'test': 'Test',
+ 'generate': 'Generate',
+ 'package': 'Package'
+ },
+ logger: Ext.create('Ext.log.Logger', {
+ writers: {
+ cli: Ext.create('Command.log.writer.Cli', {
+ formatter: Ext.create('Command.log.formatter.Cli')
+ })
+ },
+ minPriority: 'verbose'
+ })
+ });
+ command.run(Array.prototype.slice.call(process.argv, 2));
+})();
4 sdk/command/senchadebug
@@ -0,0 +1,4 @@
+#!/bin/sh
+DIR=$(dirname $(which $0))
+export NODE_PATH=$DIR/vendor/nodejs/node_modules
+$DIR/vendor/nodejs/osx/node --debug-brk $DIR/sencha.js $*
300 sdk/command/src/Cli.js
@@ -0,0 +1,300 @@
+/**
+ * @class Command.Cli
+ * @author Jacky Nguyen <jacky@sencha.com>
+ */
+Ext.define('Command.Cli', {
+ config: {
+ version: '',
+ logger: null,
+ currentPath: '',
+ modules: {}
+ },
+
+ modules: {},
+
+ templates: {},
+
+ constructor: function(config) {
+ var platformName = process.platform;
+
+ if (platformName === 'win32') {
+ platformName = 'win';
+ }
+ else if (platformName === 'darwin') {
+ platformName = 'osx';
+ }
+ else {
+ platformName = 'linux';
+
+ if (/64/.test(process.arch)) {
+ platformName += '64';
+ }
+ }
+
+ this.platformName = platformName;
+
+ this.initConfig(config);
+ },
+
+ applyVersion: function(version) {
+ return new Ext.Version(version);
+ },
+
+ applyModules: function(modules) {
+ var classManager = Ext.ClassManager,
+ alias, name;
+
+ for (alias in modules) {
+ if (modules.hasOwnProperty(alias)) {
+ name = modules[alias];
+ classManager.setAlias('Command.module.' + name, 'module.' + alias);
+ }
+ }
+
+ return modules;
+ },
+
+ run: function(args) {
+ var options = this.parseArguments(args),
+ targets = options.targets,
+ moduleName = targets.shift(),
+ action = targets.shift(),
+ module;
+
+ if (!moduleName || !(module = this.getModule(moduleName))) {
+ return this.printUsage();
+ }
+
+ if (!action || !module.hasAction(action)) {
+ return this.printUsage(moduleName);
+ }
+
+ try {
+ this.execute(module, action, options);
+ }
+ catch (e) {
+ this.error(e.message);
+ this.printUsage(moduleName, action);
+ }
+ },
+
+ getModule: function(name) {
+ var modules = this.modules,
+ module = modules[name];
+
+ if (!module) {
+ try {
+ module = Ext.createByAlias('module.' + name, this);
+ }
+ catch (e) {
+ return null;
+ }
+
+ modules[name] = module;
+ }
+
+ return module;
+ },
+
+ execute: function(module, action, options) {
+ var rules = module.getActionRules(action).slice(1),
+ args = [],
+ targets = options.targets,
+ i, ln, arg, value, name, longName, shortName, type, defaultValue;
+
+ for (i = 0,ln = rules.length; i < ln; i++) {
+ arg = rules[i];
+
+ longName = arg[0];
+ shortName = arg[1];
+ type = arg[3];
+ defaultValue = arg[4];
+ name = '--' + longName;
+
+ if (options.hasOwnProperty(longName)) {
+ value = this.formatArgumentValue(options[longName], type, name);
+ }
+ else if (shortName && options.hasOwnProperty(shortName)) {
+ name = '-' + shortName;
+ value = this.formatArgumentValue(options[shortName], type, name);
+ }
+ else {
+ value = targets.shift();
+
+ if (value !== undefined) {
+ value = this.formatArgumentValue(value, type, name);
+ }
+ else if (defaultValue !== undefined && defaultValue !== null) {
+ value = defaultValue;
+ }
+ else {
+ throw new Error("Missing required value for argument: '" + name + "'");
+ }
+ }
+
+ args.push(value);
+ }
+
+ module[action].apply(module, args);
+ },
+
+ formatArgumentValue: function(value, type, name) {
+ var errorMessagePrefix = "Invalid value of: '" + value + "' for argument: '" + name + "', ";
+
+ switch (type) {
+ case "number":
+ if (isNaN(value)) {
+ throw new Error(errorMessagePrefix + "must be a valid number");
+ }
+ return Number(value);
+ break;
+
+ case "array":
+ if (typeof value != 'string') {
+ throw new Error(errorMessagePrefix + "must be a valid comma-separated list of items");
+ }
+ return value.split(',');
+ break;
+
+ case "boolean":
+ if (value === "yes") {
+ value = true;
+ }
+ else if (value === "no") {
+ value = false;
+ }
+ return Boolean(value);
+ break;
+
+ default:
+ return String(value);
+ }
+ },
+
+ getTemplate: function(name) {
+ var templates = this.templates,
+ template = templates[name],
+ filePath;
+
+ if (!template) {
+ filePath = require('path').resolve(this.getCurrentPath(), 'templates/' + name + '.tpl');
+ templates[name] = template = Ext.create('Ext.XTemplate', this.getModule('fs').read(filePath));
+ }
+
+ return template;
+ },
+
+ printUsage: function(moduleName, actionName) {
+ var modules = [],
+ actions = [],
+ module, info;
+
+ if (!moduleName) {
+ Ext.Object.each(this.getModules(), function(alias) {
+ modules.push({
+ name: alias,
+ description: this.getModule(alias).description
+ });
+ }, this);
+
+ console.log(this.getTemplate('modules').apply({
+ version: this.getVersion().toString(),
+ modules: modules
+ }));
+ }
+ else if (!actionName) {
+ module = this.getModule(moduleName);
+
+ Ext.Object.each(module.actions, function(name, args) {
+ actions.push({
+ name: name,
+ description: args[0],
+ args: args.slice(1)
+ });
+ });
+
+ console.log(this.getTemplate('actions').apply({
+ name: moduleName,
+ description: module.description,
+ actions: actions
+ }));
+ }
+ else {
+ module = this.getModule(moduleName);
+ info = module.actions[actionName];
+
+ console.log(this.getTemplate('action').apply({
+ module: moduleName,
+ name: actionName,
+ description: info[0],
+ args: info.slice(1)
+ }));
+ }
+ },
+
+ parseArguments: function(args) {
+ var targets = [],
+ options = {
+ targets: targets
+ },
+ key = null,
+ i, ln, option, match;
+
+ for (i = 0, ln = args.length; i < ln; i++) {
+ option = args[i];
+
+ if (key !== null) {
+ if (!option.match(/^-{1,2}([^-])/i)) {
+ options[key] = option;
+ key = null;
+ continue;
+ }
+
+ options[key] = true;
+ key = null;
+ }
+
+
+ if (match = option.match(/^--([^=]+)=(.*)$/i)) {
+ options[match[1]] = match[2];
+ }
+ else if ((match = option.match(/^--(.+)$/i)) || (match = option.match(/^-(.)$/i))) {
+ key = match[1];
+ }
+ else if (match = option.match(/^-(.+)$/i)) {
+ match[1].split('').forEach(function(a) {
+ options[a] = true;
+ });
+ }
+ else {
+ targets.push(option);
+ }
+ }
+
+ if (key !== null) {
+ options[key] = true;
+ }
+
+ return options;
+ },
+
+ doLog: function(message, priority, stackLevel) {
+ return this.getLogger().log(message, priority, (stackLevel !== undefined) ? stackLevel : 2);
+ },
+
+ log: function(message) {
+ return this.doLog(message, 'verbose');
+ },
+
+ info: function(message) {
+ return this.doLog(message, 'info');
+ },
+
+ warn: function(message) {
+ return this.doLog(message, 'warn');
+ },
+
+ error: function(message) {
+ return this.doLog(message, 'error');
+ }
+});
179 sdk/command/src/Preprocessor.js
@@ -0,0 +1,179 @@
+/**
+ * @class Command.Preprocessor
+ * @author Jacky Nguyen <jacky@sencha.com>
+ */
+Ext.define('Command.Preprocessor', {
+ statics: {
+ getInstance: function() {
+ if (!this.instance) {
+ this.instance = new this();
+ }
+
+ return this.instance;
+ }
+ },
+
+ params: {},
+
+ process: function(filePath) {
+ // This is currently not memory-efficient since it reads the whole file's content at once.
+ // However nodejs doesn't have a proper / easy way to "readLine" synchronously
+ // And it takes a ridiculous amount of effort to do so
+ var lineStack = Ext.create('Command.preprocessor.LineStack', filePath);
+
+ return Ext.create('Command.preprocessor.Statement').process(lineStack);
+ },
+
+ evaluate: function(name, value) {
+ var params = this.params,
+ modifier = null,
+ param = (params.hasOwnProperty(name)) ? params[name] : false,
+ match;
+
+ if (value === undefined) {
+ value = true;
+ }
+
+ if (Ext.isString(value)) {
+ match = value.match(/^(!=*|<=|>=|<|>|=+)/);
+
+ if (match) {
+ modifier = match[0];
+ value = value.slice(modifier.length);
+ }
+
+ // Boolean
+ if (value === 'true') {
+ value = true;
+ }
+ else if (value === 'false') {
+ value = false;
+ }
+ // Numeric
+ else if (!isNaN(value)) {
+ value = parseFloat(value);
+ }
+ }
+
+// Logger.log('[DEBUG][Parser#evaluate] name:"' + name + '", modifier:'+modifier+', param:"' + param + '", value:"' + value + '"');
+
+ switch (modifier) {
+ case '!==':
+ case '!=':
+ case '!':
+ return (param !== value);
+ case '>':
+ return (param > value);
+ case '<':
+ return (param < value);
+ case '<=':
+ return (param <= value);
+ case '>=':
+ return (param >= value);
+ case '==':
+ return (param == value);
+ case '=':
+ case '===':
+ default:
+ return (param === value);
+ }
+ },
+
+ setParams: function(params) {
+ this.params = params || {};
+ },
+
+ isCloseOf: function(string, statement) {
+ if (!statement.type) {
+ return false;
+ }
+
+ return string.trim().match(new RegExp("^\\/\\/(?:\\t|\\s)*<\\/" + ((statement.isInverted) ? "!" : "") +
+ statement.type + ">$")) !== null;
+ },
+
+ isStatement: function(string) {
+ return this.parseStatementParts(string) !== null;
+ },
+
+ parseStatementParts: function(string) {
+ return string.trim().match(/^\/\/(?:\t|\s)*<([^\/]+)>$/);
+ },
+
+ parseStatementProperties: function(string) {
+ var properties = {},
+ expect = function(regexp) {
+ var result = string.match(regexp);
+
+ if (result !== null) {
+ string = string.slice(result[0].length);
+ return result[0];
+ }
+
+ return null;
+ },
+ name, equalSign, valueWrapper, valueCheck, value;
+
+ while (string.length > 0) {
+ expect(/^[^\w]+/i);
+ name = expect(/^[\w\.\-_]+/i);
+
+ if (name === null) {
+ break;
+ }
+
+ equalSign = expect(/^=/);
+
+ if (equalSign === null) {
+ properties[name] = true;
+ continue;
+ }
+
+ valueWrapper = expect(/^('|")/i);
+ valueCheck = valueWrapper || "\\s";
+
+ value = expect(new RegExp('^[^' + valueCheck + ']+'));
+
+ if (valueWrapper !== null) {
+ expect(new RegExp(valueWrapper));
+ }
+
+ properties[name] = value;
+ }
+
+ return properties;
+ },
+
+ parseStatement: function(string) {
+ string = string.trim();
+
+ var parts = this.parseStatementParts(string),
+ typeMatch, statement;
+
+ // Check if it's actually a valid statement
+ if (parts === null) {
+ return false;
+ }
+
+ string = parts[1];
+
+ typeMatch = string.match(/^(!)?([\w]+)/i);
+
+ if (typeMatch === null) {
+ return false;
+ }
+
+ statement = {
+ properties: {}
+ };
+
+ statement.type = typeMatch[2];
+ statement.isInverted = (typeMatch[1] !== undefined);
+
+ string = string.substr(typeMatch[0].length, string.length).trim();
+ statement.properties = this.parseStatementProperties(string);
+
+ return statement;
+ }
+
+});
53 sdk/command/src/log/formatter/Cli.js
@@ -0,0 +1,53 @@
+Ext.define('Command.log.formatter.Cli', {
+ extend: 'Ext.log.formatter.Default',
+
+ styles: {
+ 'bold' : [1, 22],
+ 'italic' : [3, 23],
+ 'underline' : [4, 24],
+ 'inverse' : [7, 27],
+ //grayscale
+ 'white' : [37, 39],
+ 'grey' : [90, 39],
+ 'black' : [30, 39],
+ //colors
+ 'blue' : [34, 39],
+ 'cyan' : [36, 39],
+ 'green' : [32, 39],
+ 'magenta' : [35, 39],
+ 'red' : [31, 39],
+ 'yellow' : [33, 39]
+ },
+
+ priorityStyle: {
+ verbose: ['grey', 'bold'],
+ info: ['green', 'bold'],
+ deprecate: ['yellow', 'bold'],
+ warn: ['magenta', 'bold'],
+ error: ['red', 'bold']
+ },
+
+ format: function(event) {
+ var priority = event.priorityName,
+ priorityStyles = this.priorityStyle[priority];
+
+ return require('util').format('%s %s',
+ this.style('['+priority.toUpperCase()+']', priorityStyles),
+// this.style('['+event.callerDisplayName+']', ['grey']),
+ event.message);
+ },
+
+ style: function(text, styles) {
+ var style, i, ln, data;
+
+ styles = Ext.Array.from(styles);
+
+ for (i = 0,ln = styles.length; i < ln; i++) {
+ style = styles[i];
+ data = this.styles[style];
+ text = '\033['+data[0]+'m' + text + '\033['+data[1]+'m';
+ }
+
+ return text;
+ }
+});
7 sdk/command/src/log/writer/Cli.js
@@ -0,0 +1,7 @@
+Ext.define('Command.log.writer.Cli', {
+ extend: 'Ext.log.writer.Writer',
+
+ doWrite: function(event) {
+ console.log(event.message);
+ }
+});
67 sdk/command/src/module/Abstract.js
@@ -0,0 +1,67 @@
+/**
+ * @class Command.module.Abstract
+ * @author Jacky Nguyen <jacky@sencha.com>
+ */
+Ext.define('Command.module.Abstract', {
+ actions: {},
+
+ constructor: function(cli) {
+ this.cli = cli;
+ },
+
+ getModule: function(name) {
+ return this.cli.getModule(name);
+ },
+
+ getTemplate: function(name) {
+ return this.cli.getTemplate(name);
+ },
+
+ hasAction: function(action) {
+ return this.actions.hasOwnProperty(action);
+ },
+
+ getActionRules: function(action) {
+ return this.actions[action];
+ },
+
+ getVendorPath: function(name) {
+ return require('path').resolve(this.cli.getCurrentPath(), 'vendor/' + name);
+ },
+
+ escapeShell: function(cmd) {
+ if (!cmd) {
+ return '';
+ }
+
+ return '"' + cmd + '"';
+ },
+
+ exec: function(command, args, callback) {
+ var util = require('util');
+
+ if (typeof args == 'function') {
+ callback = args;
+ args = [];
+ }
+
+ args = args.map(function(arg) {
+ return this.escapeShell(arg);
+ }, this);
+ args.unshift(command);
+
+ command = util.format.apply(util, args);
+ callback = callback.bind(this);
+
+ require('child_process').exec(command, callback);
+ }
+
+}, function() {
+ ['log', 'info', 'warn', 'error'].forEach(function(name) {
+ this.addMember(name, function() {
+ var args = Ext.Array.from(arguments);
+ args.push(name);
+ return this.cli.doLog.apply(this.cli, args);
+ });
+ }, this);
+});
316 sdk/command/src/module/Application.js
@@ -0,0 +1,316 @@
+/**
+ * @class Command.module.Application
+ * @author Jacky Nguyen <jacky@sencha.com>
+ */
+Ext.define('Command.module.Application', {
+ extend: 'Command.module.Abstract',
+
+ description: 'Resolve application dependencies and build for production',
+
+ actions: {
+ create: [
+ "(Alias to 'sencha generate app') Generate a new project with the recommended structure",
+ ['name', 'n', 'The namespace of the application to create. ' +
+ 'This will be used as the prefix for all your classes', 'string', null, 'MyApp'],
+ ['path', 'p', 'The directory path to generate this application to.', 'string', null, '/path/to/myapp'],
+ ['library', 'l', "The library's build to develop your application with, either 'core' or 'all'. " +
+ "Defaults to 'core'", 'string', 'core', 'all']
+ ],
+ resolve: [
+ "Generate a list of dependencies in the exact loading order for the given application. " +
+ "Note that the resolved paths are relative to the given application's HTML document",
+ ['uri', 'u', 'The URI to the application\'s HTML document', 'string', null, 'http://localhost/myapp/index.html'],
+ ['output', 'o', 'The file path to write the results to in JSON format.', 'string', null, 'dependencies.json']
+ ],
+ build: [
+ "Build the application at the current working directory to the given path",
+ ['environment', 'e', "The build environment, either 'testing', 'package', 'production', or 'native'" +
+ "\n " +
+ "+ 'testing' is meant for QA prior to production. All JavaScript and CSS Files are bundled, but not minified" +
+ "\n " +
+ "+ 'package' creates a self-contained, re-distributable production build that " +
+ "\n " +
+ "normally runs from local file system without the need for a web server" +
+ "\n " +
+ "+ 'production' creates a production build that is normally hosted on a web server and " +
+ "\n " +
+ "serve multiple clients (devices). The build is offline-capable and has built-in " +
+ "\n " +
+ "OTA delta updating feature" +
+ "\n " +
+ "+ 'native' first generates a 'package' build, then packages it as a native " +
+ "\n " +
+ "application, ready to be deployed to native platforms",
+ 'string', null, 'production'],
+ ['destination', 'd', "The directory path to build this application to. " +
+ "\n " +
+ "If none given, the default path specified inside 'app.json' is used", 'string', '', '/path/to/deploy/myapp'],
+ ['archive', 'a', "The directory path where all previous builds were stored," +
+ "\n " +
+ "needed to generate deltas between updates (for production only). " +
+ "\n " +
+ "If none given, the default path specified inside 'app.json' is used",
+ 'string', '', '/path/to/myapp/archive']
+ ]
+ },
+
+ create: function() {
+ var module = this.getModule('generate');
+
+ module.app.apply(module, arguments);
+ },
+
+ resolve: function(uri, output, callback) {
+ var parsedUri = require('url').parse(uri);
+
+ if (!/^file|http/.test(parsedUri.protocol)) {
+ uri = 'file:///' + require('path').resolve(uri).replace(/\\/g, '/');
+ }
+
+ this.exec('%s %s %s', [
+ this.getVendorPath('phantomjs/' + this.cli.platformName + '/phantomjs'),
+ this.getVendorPath('phantomjs/dependencies.js'),
+ uri
+ ], function(error, stdout) {
+ if (error) {
+ this.error(stdout);
+ }
+ else {
+ if (output) {
+ this.getModule('fs').write(output, stdout);
+ }
+
+ if (callback) {
+ callback(JSON.parse(stdout));
+ }
+ }
+ });
+ },
+
+ build: function(environment, destination, archive) {
+ var nativePackaging = false;
+
+ if (environment == 'native') {
+ environment = 'package';
+ nativePackaging = true;
+ }
+
+ if (!/^testing|package|production$/.test(environment)) {
+ throw new Error("Invalid environment argument of: '"+environment+"'," +
+ " must be either 'testing', 'package', 'production' or 'native'");
+ }
+
+ var path = require('path'),
+ src = process.cwd(),
+ fs = this.getModule('fs'),
+ sdk = path.resolve(src, fs.read('.senchasdk').trim()),
+ config = fs.readJson(path.join(src, 'app.json')),
+ jsAssets = config.js || [],
+ cssAssets = config.css || [],
+ extras = config.extras,
+ appCache = config.appCache,
+ preprocessor = Ext.require('Command.Preprocessor').getInstance(),
+ nodeFs = require('fs'),
+ indexHtml, assets, file, destinationFile, files,
+ appJs, assetsCount, processedAssetsCount,
+ packagerConfig, packagerJson, processIndex;
+
+ preprocessor.setParams(config.buildOptions || {});
+
+ if (!destination) {
+ destination = config.buildPaths[environment];
+ }
+
+ if (!archive) {
+ archive = config.archivePath;
+ }
+
+ destination = path.resolve(destination);
+ archive = path.resolve(archive);
+
+ appJs = path.join(destination, 'app.js');
+
+ this.info("Deploying your application to " + destination);
+
+ fs.mkdir(destination);
+
+ jsAssets = jsAssets.map(function(asset) {
+ if (typeof asset == 'string') {
+ asset = { path: asset };
+ }
+ asset.type = 'js';
+ return asset;
+ });
+
+ cssAssets = cssAssets.map(function(asset) {
+ if (typeof asset == 'string') {
+ asset = { path: asset };
+ }
+ asset.type = 'css';
+ return asset;
+ });
+
+ assets = jsAssets.concat(cssAssets).filter(function(asset) {
+ return !asset.shared || (environment != 'production');
+ });
+
+ assets.forEach(function(asset) {
+ file = asset.path;
+ fs.copyFile(path.join(src, file), path.join(destination, file));
+ this.info("Copied " + file);
+ }, this);
+
+ extras.forEach(function(extra) {
+ fs.copy(path.join(src, extra), path.join(destination, extra));
+ this.info("Copied " + extra);
+ }, this);
+
+ processIndex = function(callback) {
+ var appJson = JSON.stringify({
+ id: config.id,
+ js: jsAssets,
+ css: cssAssets
+ });
+
+ fs.write(path.join(destination, 'app.json'), appJson);
+ this.info("Generated app.json");
+
+ indexHtml = fs.read(path.join(src, 'index.html'));
+
+ if (environment == 'production' && appCache) {
+ indexHtml = indexHtml.replace('<html manifest=""', '<html manifest="cache.manifest"');
+ }
+
+ fs.minify(path.join(sdk, 'microloader', (environment == 'production' ? 'production' : 'testing')+'.js'), null, 'closurecompiler', function(content) {
+ indexHtml = indexHtml.replace(/<script id="microloader"([^<]+)<\/script>/,
+ '<script type="text/javascript">' +
+ content + ';Ext.blink(' + (environment == 'production' ? JSON.stringify({
+ id: config.id
+ }) : appJson) + ')' +
+ '</script>');
+
+ fs.write(path.join(destination, 'index.html'), indexHtml);
+ this.info("Embedded microloader into index.html");
+
+ if (callback) {
+ callback();
+ }
+ }.bind(this));
+ }.bind(this);
+
+ this.info("Resolving your application dependencies...");
+ this.resolve(path.join(src, 'index.html'), null, function(dependencies) {
+ this.info("Found " + dependencies.length + " dependencies. Concatenating all into app.js...");
+
+ files = dependencies.map(function(dependency) {
+ return path.join(src, dependency.path);
+ });
+
+ files.push(appJs);
+
+ fs.concat(files, path.join(destination, 'app.all.js'), "\n");
+
+ nodeFs.unlinkSync(appJs);
+ nodeFs.renameSync(path.join(destination, 'app.all.js'), appJs);
+
+ processedAssetsCount = 0;
+ assetsCount = assets.length;
+ assets.forEach(function(asset) {
+ file = asset.path;
+ destinationFile = path.join(destination, file);
+
+ if (asset.type == 'js') {
+ fs.write(destinationFile, preprocessor.process(destinationFile));
+ this.info("Processed " + file);
+ }
+
+ if (environment == 'testing') {
+ return;
+ }
+
+ this.info("Minifying " + file);
+
+ fs.minify(destinationFile, destinationFile, null, function(destinationFile, file, asset) {
+ this.info("Minified " + file);
+
+ if (environment == 'production') {
+ var version = fs.checksum(destinationFile);
+ asset.version = version;
+
+ fs.prependFile(destinationFile, '/*' + version + '*/');
+ fs.copyFile(destinationFile, path.join(archive, file, version));
+
+ if (asset.update === 'delta') {
+ nodeFs.readdirSync(path.join(archive, file)).forEach(function(archivedVersion) {
+ if (archivedVersion === version) {
+ return;
+ }
+
+ var deltaFile = path.join(destination, 'deltas', file, archivedVersion + '.json');
+
+ fs.write(deltaFile, '');
+ fs.delta(
+ path.join(archive, file, archivedVersion), destinationFile, deltaFile,
+ function() {
+ this.info("Generated delta for: '" + file + "' from hash: '" +
+ archivedVersion + "' to hash: '" + version + "'");
+ }.bind(this)
+ );
+
+ }, this);
+ }
+ }
+
+ if (++processedAssetsCount == assetsCount) {
+ processIndex(function() {
+ if (environment == 'production' && appCache) {
+ appCache.cache = appCache.cache.map(function(cache) {
+ var checksum = '';
+
+ if (!/^(\/|(.*):\/\/)/.test(cache)) {
+ this.info("Generating checksum for appCache item: " + cache);
+ checksum = fs.checksum(path.join(destination, cache));
+ }
+
+ return {
+ uri: cache,
+ checksum: checksum
+ }
+ }, this);
+
+ fs.write(path.join(destination, 'cache.manifest'), this.getTemplate('cache.manifest').apply(appCache));
+ this.info("Generated cache.manifest");
+ }
+
+ if (nativePackaging) {
+ packagerJson = fs.read(path.join(src, 'packager.json'));
+ packagerConfig = Ext.JSON.decode(packagerJson);
+
+ if (packagerConfig.platform.match(/iOS/)) {
+ fs.copyDirectory(path.join(src, 'resources', 'icons'), destination);
+ fs.copyDirectory(path.join(src, 'resources', 'loading'), destination);
+ }
+
+ packagerConfig.inputPath = destination;
+ packagerConfig.outputPath = path.resolve(config.buildPaths.native);
+ fs.mkdir(packagerConfig.outputPath);
+ fs.writeJson(path.join(src, 'packager.temp.json'), packagerConfig);
+
+ this.info("Packaging your application as a native app...");
+
+ this.getModule('package').run('packager.temp.json', function() {
+ nodeFs.unlinkSync(path.join(src, 'packager.temp.json'));
+ });
+ }
+ }.bind(this));
+ }
+ }.bind(this, destinationFile, file, asset));
+ }, this);
+
+ if (environment == 'testing') {
+ processIndex();
+ }
+
+ }.bind(this));
+ }
+});
297 sdk/command/src/module/FileSystem.js
@@ -0,0 +1,297 @@
+/**
+ * @class Command.module.FileSystem
+ * @author Jacky Nguyen <jacky@sencha.com>
+ */
+Ext.define('Command.module.FileSystem', {
+ extend: 'Command.module.Abstract',
+
+ description: 'A set of useful utility actions to work with files. ' +
+ 'Most commonly used actions are: concat, minify, delta',
+
+ actions: {
+ concat: [
+ "Concatenate multiple files into one",
+ ['from', 'f', 'List of files to concatenate, comma-separated', 'array', null, 'foo.js,bar.js,baz.js'],
+ ['to', 't', 'The destination file to write concatenated content', 'string', null, 'target.js']
+ ],
+ minify: [
+ "Minify a JavaScript file, currently support YUICompressor (default), Closure Compiler and UglifyJS",
+ ['from', 'f', 'Path to the file to minify', 'string', null, 'app.js'],
+ ['to', 't', 'Path to the destination file to write minified content to.', 'string', null, 'app-minified.js'],
+ ['compressor', 'c',
+ 'The name of the compressor to use, can be either: "yuicompressor", ' +
+ '"uglifyjs" or "closurecompiler". Defaults to "yuicompressor"', 'string', 'yuicompressor', 'uglifyjs']
+ ],
+ delta: [
+ "Generates deltas between two files in JSON format",
+ ['from', 'f', 'Path to the dictionary file', 'string', null, 'version1.js'],
+ ['to', 't', 'Path to the target file to compare to', 'string', null, 'version2.js'],
+ ['delta', 'd', 'Path to a JSON file to write the delta content to', 'string', null, 'delta.json']
+ ]
+ },
+
+ /**
+ * Concatenate multiple files into one
+ * @param fromFiles
+ * @param toFile
+ */
+ concat: function(fromFiles, toFile, separator) {
+ var fs = require('fs'),
+ i, ln, fromFile, fd;
+
+ separator = separator || '';
+
+ fd = fs.openSync(toFile, 'w');
+
+ for (i = 0,ln = fromFiles.length; i < ln; i++) {
+ fromFile = fromFiles[i];
+ fs.writeSync(fd, this.read(fromFile) + separator);
+ }
+
+ fs.closeSync(fd);
+ },
+
+ /**
+ * Minify a JavaScript file, currently support YUICompressor (default), Closure Compiler and UglifyJS
+ * @param fromFiles
+ * @param toFile
+ */
+ minify: function(fromFile, toFile, compressor, callback) {
+ var command, jarPath, toArg, content;
+
+ callback = callback || Ext.emptyFn;
+
+ if (compressor === 'uglifyjs') {
+ var uglifyjs = require('uglify-js'),
+ jsp = uglifyjs.parser,
+ pro = uglifyjs.uglify,
+ ast = jsp.parse(this.read(fromFile));
+
+ ast = pro.ast_mangle(ast); // get a new AST with mangled names
+ ast = pro.ast_squeeze(ast); // get an AST with compression optimizations
+ content = pro.gen_code(ast);
+
+ if (toFile) {
+ this.write(toFile, content);
+ callback();
+ }
+ else {
+ callback(content);
+ }
+ }
+ else {
+ if (compressor === 'closurecompiler') {
+ command = 'java -jar %s ' + (toFile ? '--js_output_file %s' : '%s') + ' --js %s';
+ jarPath = this.getVendorPath('closurecompiler/compiler.jar');
+ }
+ else {
+ command = 'java -jar %s ' + (toFile ? '-o %s' : '%s') + ' %s';
+ jarPath = this.getVendorPath('yuicompressor/yuicompressor.jar');
+ }
+
+ this.exec(command, [jarPath, toFile, fromFile], function(error, stdout, stderr) {
+ if (error) {
+ this.error(error);
+ this.error(stderr);
+ }
+ else {
+ if (!toFile) {
+ callback(stdout);
+ }
+ else {
+ if (stdout) {
+ this.info(stdout);
+ }
+ callback();
+ }
+ }
+ });
+ }
+ },
+
+ /**
+ * Generates deltas between two files in JSON format
+ * @param fromFile
+ * @param toFile
+ * @param delta
+ */
+ delta: function(fromFile, toFile, delta, callback) {
+ this.exec('%s encode -json -dictionary %s -target %s -delta %s --stats', [
+ this.getVendorPath('vcdiff/' + this.cli.platformName + '/vcdiff'),
+ fromFile,
+ toFile,
+ delta
+ ], function(error, stdout, stderr) {
+ if (error) {
+ this.error(stderr);
+ }
+ else {
+ if (stdout) {
+ this.info(stdout);
+ }
+
+ // Fix malformed JSON generated from vcdiff (trailing comma), e.g [1,2,3,] -> [1,2,3]
+ var content = this.read(delta);
+ this.write(delta, content.substring(0, content.length - 2) + ']');
+ callback();
+ }
+ });
+ },
+
+ mkdir: function() {
+ var fs = require('fs'),
+ path = require('path'),
+ names = Array.prototype.slice.call(arguments),
+ ln = names.length,
+ i, j, subLn, name, parentDirName, dirNames;
+
+ for (i = 0; i < ln; i++) {
+ name = names[i];
+ dirNames = [];
+
+ while (!path.existsSync(name)) {
+ dirNames.unshift(name);
+ parentDirName = path.dirname(name);
+
+ if (parentDirName === name) {
+ break;
+ }
+
+ name = parentDirName;
+ }
+
+ for (j = 0, subLn = dirNames.length; j < subLn; j++) {
+ name = dirNames[j];
+ fs.mkdirSync(name);
+ }
+ }
+ },
+
+ read: function(file) {
+ return require('fs').readFileSync(file, 'utf8');
+ },
+
+ readJson: function(file) {
+ return Ext.JSON.decode(this.read(file));
+ },
+
+ write: function(file, content) {
+ var path = require('path');
+
+ if (!path.existsSync(file)) {
+ this.mkdir(path.dirname(file));
+ }
+
+ require('fs').writeFileSync(file, content, 'utf8');
+ },
+
+ writeJson: function(file, object, beautify) {
+ return this.write(file, beautify ? JSON.stringify(object, null, 4) : JSON.stringify(object));
+ },
+
+ prependFile: function(file, content) {
+ this.write(file, content + this.read(file));
+ },
+
+ appendFile: function(file, content) {
+ var fs = require('fs'),
+ fd = fs.openSync(file, 'a');
+
+ fs.writeSync(fd, content);
+ fs.closeSync(fd);
+ },
+
+ copyFile: function(src, destination) {
+ var fs = require('fs'),
+ path = require('path');
+
+ if (!path.existsSync(destination)) {
+ this.mkdir(path.dirname(destination));
+ }
+
+ fs.writeFileSync(destination, fs.readFileSync(src));
+ fs.chmodSync(destination, fs.statSync(src).mode.toString(8).substr(-3));
+ },
+
+ removeDirectory: function(directory) {
+ var fs = require('fs'),
+ path = require('path'),
+ files, filePath, fileStats, i, filesLength;
+
+ files = fs.readdirSync(directory);
+ filesLength = files.length;
+
+ if (filesLength) {
+ for (i = 0; i < filesLength; i += 1) {
+ filePath = path.join(directory, files[i]);
+
+ fileStats = fs.statSync(filePath);
+
+ if (fileStats.isFile()) {
+ fs.unlinkSync(filePath);
+ }
+ else if (fileStats.isDirectory()) {
+ this.removeDirectory(filePath);
+ }
+ }
+ }
+
+ fs.rmdirSync(directory);
+ },
+
+ copyDirectory: function(src, destination) {
+ var fs = require('fs'),
+ path = require('path'),
+ files, file, stats, i, ln, link, srcFile, destinationFile;
+//
+// try {
+// if (fs.statSync(destination).isDirectory()) {
+// this.removeDirectory(destination);
+// }
+// }
+// catch (e) {}
+
+ this.mkdir(destination);
+
+ files = fs.readdirSync(src);