zena 1.2.7 → 1.2.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (407) hide show
  1. data/History.txt +80 -25
  2. data/Rakefile +2 -2
  3. data/app/controllers/columns_controller.rb +2 -2
  4. data/app/controllers/nodes_controller.rb +22 -29
  5. data/app/controllers/user_sessions_controller.rb +35 -10
  6. data/app/controllers/users_controller.rb +2 -2
  7. data/app/controllers/versions_controller.rb +2 -2
  8. data/app/models/group.rb +15 -1
  9. data/app/models/node.rb +109 -8
  10. data/app/models/role.rb +4 -0
  11. data/app/models/site.rb +64 -58
  12. data/app/models/template.rb +1 -1
  13. data/app/models/user.rb +135 -29
  14. data/app/models/user_session.rb +0 -1
  15. data/app/models/virtual_class.rb +11 -6
  16. data/app/views/columns/_form.html.erb +3 -1
  17. data/app/views/columns/_li.html.erb +1 -1
  18. data/app/views/columns/create.rjs +1 -1
  19. data/app/views/groups/_form.rhtml +16 -13
  20. data/app/views/relations/_form.erb +18 -6
  21. data/app/views/sites/_form.erb +12 -6
  22. data/app/views/users/_form.rhtml +23 -8
  23. data/app/views/users/_li.rhtml +14 -3
  24. data/app/views/users/index.rhtml +1 -1
  25. data/app/views/virtual_classes/_form.erb +12 -2
  26. data/app/views/zafu/default/Node-+login.zafu +8 -1
  27. data/app/views/zafu/default/Node-+search.zafu +1 -1
  28. data/bricks/acls/lib/bricks/acls.rb +1 -0
  29. data/bricks/acls/zena/migrate/20130903150356_longer_names_for_acl.rb +9 -0
  30. data/bricks/acls/zena/test/integration/acl_integration_test.rb +2 -2
  31. data/bricks/currency/lib/bricks/currency.rb +120 -0
  32. data/bricks/currency/zena/test/unit/currency_test.rb +43 -0
  33. data/bricks/fs_skin/lib/bricks/fs_skin.rb +1 -1
  34. data/bricks/fs_skin/zena/skins/blog/Node-+search.zafu +1 -1
  35. data/bricks/fs_skin/zena/skins/blog/Node.zafu +1 -1
  36. data/bricks/fs_skin/zena/test/unit/fs_skin_view_test.rb +35 -0
  37. data/bricks/pdf/lib/bricks/pdf.rb +1 -1
  38. data/bricks/sphinx/lib/bricks/sphinx.rb +2 -0
  39. data/bricks/sphinx/zena/init.rb +14 -0
  40. data/bricks/tags/zena/test/zafu/tags.yml +5 -1
  41. data/bricks/worker/lib/bricks/worker.rb +3 -2
  42. data/bricks/zena/zena/migrate/20130829093753_add_versioned_flag_to_column.rb +10 -0
  43. data/bricks/zena/zena/migrate/20130903084909_count_login_attempts.rb +11 -0
  44. data/bricks/zena/zena/migrate/20131104153126_index_fullpath.rb +10 -0
  45. data/bricks/zena/zena/migrate/20131104210011_rebuild_fullpath_after_change.rb +10 -0
  46. data/bricks/zena/zena/migrate/20131105160420_add_skin_id_to_sites.rb +9 -0
  47. data/bricks/zena/zena/migrate/20131105175822_add_profile_to_users.rb +11 -0
  48. data/bricks/zena/zena/migrate/20140213120038_fix_idx_scope.rb +13 -0
  49. data/bricks/zena/zena/migrate/20140628140247_add_site_readonly.rb +9 -0
  50. data/config/bricks.yml +8 -4
  51. data/config/gems.yml +5 -3
  52. data/db/init/base/skins/default/Node-+login.zafu +8 -1
  53. data/db/init/base/skins/default/Node-+search.zafu +1 -1
  54. data/lib/bricks/loader.rb +5 -5
  55. data/lib/gettext_strings.rb +3 -0
  56. data/lib/tasks/zena.rake +25 -22
  57. data/lib/zafu/process/context.rb +4 -0
  58. data/lib/zena/acts/secure_node.rb +3 -3
  59. data/lib/zena/app.rb +1 -0
  60. data/lib/zena/deploy.rb +1 -1
  61. data/lib/zena/deploy/template.rb +1 -1
  62. data/lib/zena/foxy_parser.rb +5 -2
  63. data/lib/zena/info.rb +1 -1
  64. data/lib/zena/site_worker.rb +2 -2
  65. data/lib/zena/test_controller.rb +5 -2
  66. data/lib/zena/use/action.rb +9 -2
  67. data/lib/zena/use/ajax.rb +20 -4
  68. data/lib/zena/use/ancestry.rb +89 -15
  69. data/lib/zena/use/authlogic.rb +8 -2
  70. data/lib/zena/use/context.rb +1 -0
  71. data/lib/zena/use/display.rb +1 -97
  72. data/lib/zena/use/forms.rb +28 -8
  73. data/lib/zena/use/html_tags.rb +16 -7
  74. data/lib/zena/use/i18n.rb +1 -1
  75. data/lib/zena/use/prop_eval.rb +6 -1
  76. data/lib/zena/use/query_node.rb +69 -4
  77. data/lib/zena/use/recursion.rb +1 -1
  78. data/lib/zena/use/refactor.rb +5 -2
  79. data/lib/zena/use/relations.rb +1 -0
  80. data/lib/zena/use/rendering.rb +7 -4
  81. data/lib/zena/use/test_helper.rb +8 -4
  82. data/lib/zena/use/upload.rb +14 -0
  83. data/lib/zena/use/urls.rb +39 -23
  84. data/lib/zena/use/version_hash.rb +5 -2
  85. data/lib/zena/use/workflow.rb +116 -70
  86. data/lib/zena/use/zafu_eval.rb +41 -0
  87. data/lib/zena/use/zafu_safe_definitions.rb +1 -0
  88. data/lib/zena/use/zafu_templates.rb +32 -26
  89. data/lib/zena/use/zazen.rb +8 -7
  90. data/locale/app.pot +5 -1
  91. data/locale/de/LC_MESSAGES/zena.mo +0 -0
  92. data/locale/de/zena.po +385 -281
  93. data/locale/en/LC_MESSAGES/zena.mo +0 -0
  94. data/locale/en/zena.po +378 -271
  95. data/locale/fr/LC_MESSAGES/zena.mo +0 -0
  96. data/locale/fr/zena.po +387 -272
  97. data/locale/it/LC_MESSAGES/zena.mo +0 -0
  98. data/locale/it/zena.po +433 -404
  99. data/locale/zena.pot +362 -268
  100. data/public/javascripts/grid.js +280 -104
  101. data/public/javascripts/zena.js +43 -15
  102. data/public/stylesheets/admin.css +8 -2
  103. data/public/stylesheets/grid.css +5 -2
  104. data/public/stylesheets/popup.css +1 -1
  105. data/test/fixtures/files/TestNode.zafu +51 -0
  106. data/test/functional/nodes_controller_test.rb +20 -5
  107. data/test/functional/user_sessions_controller_test.rb +41 -6
  108. data/test/functional/users_controller_test.rb +1 -2
  109. data/test/integration/navigation_test.rb +22 -4
  110. data/test/integration/query_node/basic.yml +7 -0
  111. data/test/integration/query_node/complex.yml +1 -1
  112. data/test/integration/query_node/errors.yml +1 -1
  113. data/test/integration/query_node/filters.yml +34 -1
  114. data/test/integration/query_node/relations.yml +6 -13
  115. data/test/integration/query_node_test.rb +22 -3
  116. data/test/integration/zafu_compiler/action.yml +1 -1
  117. data/test/integration/zafu_compiler/alias_site.yml +52 -0
  118. data/test/integration/zafu_compiler/complex.yml +1 -1
  119. data/test/integration/zafu_compiler/complex_ok.yml +5 -5
  120. data/test/integration/zafu_compiler/context.yml +1 -1
  121. data/test/integration/zafu_compiler/display.yml +56 -5
  122. data/test/integration/zafu_compiler/forms.yml +35 -2
  123. data/test/integration/zafu_compiler/meta.yml +4 -0
  124. data/test/integration/zafu_compiler/rubyless.yml +1 -1
  125. data/test/integration/zafu_compiler/safe_definitions.yml +4 -0
  126. data/test/integration/zafu_compiler/security.yml +10 -0
  127. data/test/integration/zafu_compiler/site.yml +5 -1
  128. data/test/integration/zafu_compiler/urls.yml +8 -2
  129. data/test/integration/zafu_compiler/zafu_attributes.yml +2 -1
  130. data/test/integration/zafu_compiler/zazen.yml +4 -0
  131. data/test/integration/zafu_compiler_test.rb +47 -4
  132. data/test/selenium/Grid/grid1.rsel +8 -8
  133. data/test/sites/complex/sites.yml +2 -2
  134. data/test/sites/complex/users.yml +1 -0
  135. data/test/sites/zena/columns.yml +4 -0
  136. data/test/sites/zena/sites.yml +1 -0
  137. data/test/sites/zena/users.yml +1 -0
  138. data/test/unit/node_test.rb +53 -5
  139. data/test/unit/note_test.rb +1 -1
  140. data/test/unit/relation_proxy_test.rb +20 -0
  141. data/test/unit/role_test.rb +2 -0
  142. data/test/unit/site_test.rb +28 -6
  143. data/test/unit/user_test.rb +332 -1
  144. data/test/unit/virtual_class_test.rb +55 -0
  145. data/test/unit/workflow_test.rb +175 -0
  146. data/test/unit/zena/use/ancestry_test.rb +52 -10
  147. data/test/unit/zena/use/prop_eval_test.rb +44 -0
  148. data/test/unit/zena/use/rendering_test.rb +48 -2
  149. data/test/unit/zena/use/upload_test.rb +15 -13
  150. data/test/unit/zena/use/urls_test.rb +1 -0
  151. data/vendor/plugins/ar_mysql_full_text/lib/ar_mysql_full_text.rb +39 -25
  152. data/zena.gemspec +69 -307
  153. metadata +143 -368
  154. data/vendor/TextMate/Ruby Shoulda.tmbundle/Commands/Run 2.tmCommand +0 -24
  155. data/vendor/TextMate/Ruby Shoulda.tmbundle/Commands/Run Context.tmCommand +0 -58
  156. data/vendor/TextMate/Ruby Shoulda.tmbundle/Commands/Run Focused Should.tmCommand +0 -88
  157. data/vendor/TextMate/Ruby Shoulda.tmbundle/Commands/Run.tmCommand +0 -27
  158. data/vendor/TextMate/Ruby Shoulda.tmbundle/Commands/YAML to Shoulda.tmCommand +0 -23
  159. data/vendor/TextMate/Ruby Shoulda.tmbundle/Preferences/Symbol List: Context.tmPreferences +0 -19
  160. data/vendor/TextMate/Ruby Shoulda.tmbundle/Preferences/Symbol List: Should.tmPreferences +0 -19
  161. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/Factory attributes for.tmSnippet +0 -16
  162. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/Factory build.tmSnippet +0 -16
  163. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/Factory.tmSnippet +0 -16
  164. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/Factory_define with class.tmSnippet +0 -18
  165. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/Factory_define.tmSnippet +0 -18
  166. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/Factory_next.tmSnippet +0 -16
  167. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/Factory_sequence.tmSnippet +0 -18
  168. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/assert_bad_value.tmSnippet +0 -16
  169. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/assert_contains.tmSnippet +0 -16
  170. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/assert_does_not_contain.tmSnippet +0 -16
  171. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/assert_good_value.tmSnippet +0 -16
  172. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/assert_same_elements.tmSnippet +0 -16
  173. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/assert_save.tmSnippet +0 -16
  174. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/assert_sent_email.tmSnippet +0 -18
  175. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/assert_valid.tmSnippet +0 -16
  176. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/association.tmSnippet +0 -17
  177. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/attribute.tmSnippet +0 -17
  178. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/before_should block.tmSnippet +0 -18
  179. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/context block get.tmSnippet +0 -22
  180. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/context block post.tmSnippet +0 -23
  181. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/context block with setup.tmSnippet +0 -25
  182. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/setup.tmSnippet +0 -18
  183. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should block with before proc.tmSnippet +0 -18
  184. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should block.tmSnippet +0 -18
  185. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_allow_values_for.tmSnippet +0 -16
  186. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_assign_to.tmSnippet +0 -16
  187. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_be_restful denied.tmSnippet +0 -20
  188. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_be_restful.tmSnippet +0 -20
  189. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_belong_to.tmSnippet +0 -16
  190. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_change by.tmSnippet +0 -16
  191. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_change from to.tmSnippet +0 -16
  192. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_ensure_length_at_least.tmSnippet +0 -16
  193. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_ensure_length_in_range.tmSnippet +0 -16
  194. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_ensure_length_is.tmSnippet +0 -16
  195. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_ensure_value_in_range.tmSnippet +0 -16
  196. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_eventually.tmSnippet +0 -18
  197. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_filter_params.tmSnippet +0 -16
  198. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_have_and_belong_to_many.tmSnippet +0 -16
  199. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_have_class_methods.tmSnippet +0 -16
  200. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_have_db_column.tmSnippet +0 -16
  201. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_have_db_columns.tmSnippet +0 -16
  202. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_have_index.tmSnippet +0 -16
  203. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_have_indices.tmSnippet +0 -16
  204. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_have_instance_methods.tmSnippet +0 -16
  205. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_have_many.tmSnippet +0 -16
  206. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_have_named_scope.tmSnippet +0 -16
  207. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_have_one.tmSnippet +0 -16
  208. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_have_readonly_attributes.tmSnippet +0 -16
  209. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_not_allow_mass_assignment_of.tmSnippet +0 -16
  210. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_not_allow_values_for.tmSnippet +0 -16
  211. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_not_assign_to.tmSnippet +0 -16
  212. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_not_change.tmSnippet +0 -16
  213. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_not_set_the_flash.tmSnippet +0 -16
  214. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_redirect_to.tmSnippet +0 -16
  215. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_render_a_form.tmSnippet +0 -16
  216. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_render_template.tmSnippet +0 -16
  217. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_render_with_layout.tmSnippet +0 -16
  218. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_render_without_layout.tmSnippet +0 -16
  219. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_respond_with.tmSnippet +0 -16
  220. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_respond_with_content_type.tmSnippet +0 -16
  221. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_return_from_session.tmSnippet +0 -16
  222. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_route.tmSnippet +0 -16
  223. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_set_the_flash_to.tmSnippet +0 -16
  224. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_validate_acceptance_of.tmSnippet +0 -16
  225. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_validate_numericality_of.tmSnippet +0 -16
  226. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_validate_presence_of.tmSnippet +0 -16
  227. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_validate_uniqueness_of with scope.tmSnippet +0 -16
  228. data/vendor/TextMate/Ruby Shoulda.tmbundle/Snippets/should_validate_uniqueness_of.tmSnippet +0 -16
  229. data/vendor/TextMate/Ruby Shoulda.tmbundle/Support/RubyMate/catch_exception.rb +0 -39
  230. data/vendor/TextMate/Ruby Shoulda.tmbundle/Support/RubyMate/run_script.rb +0 -104
  231. data/vendor/TextMate/Ruby Shoulda.tmbundle/Support/RubyMate/stdin_dialog.rb +0 -14
  232. data/vendor/TextMate/Ruby Shoulda.tmbundle/Support/RubyMate/test.rb +0 -17
  233. data/vendor/TextMate/Ruby Shoulda.tmbundle/Support/RubyMate/todo.txt +0 -13
  234. data/vendor/TextMate/Ruby Shoulda.tmbundle/Support/bin/yaml_to_shoulda.rb +0 -25
  235. data/vendor/TextMate/Ruby Shoulda.tmbundle/Syntaxes/Ruby on Rails (Shoulda).tmLanguage +0 -166
  236. data/vendor/TextMate/Ruby Shoulda.tmbundle/info.plist +0 -304
  237. data/vendor/TextMate/Zena.tmbundle/Commands/Run all yaml tests.tmCommand +0 -37
  238. data/vendor/TextMate/Zena.tmbundle/Commands/Run focused yaml test.tmCommand +0 -52
  239. data/vendor/TextMate/Zena.tmbundle/Support/RubyMate/catch_exception.rb +0 -39
  240. data/vendor/TextMate/Zena.tmbundle/Support/RubyMate/run_script.rb +0 -118
  241. data/vendor/TextMate/Zena.tmbundle/Support/RubyMate/stdin_dialog.rb +0 -14
  242. data/vendor/TextMate/Zena.tmbundle/info.plist +0 -17
  243. data/vendor/plugins/selenium-on-rails/CHANGELOG +0 -125
  244. data/vendor/plugins/selenium-on-rails/LICENSE-2.0.txt +0 -202
  245. data/vendor/plugins/selenium-on-rails/README.md +0 -202
  246. data/vendor/plugins/selenium-on-rails/Rakefile +0 -38
  247. data/vendor/plugins/selenium-on-rails/doc/classes/SeleniumController.html +0 -265
  248. data/vendor/plugins/selenium-on-rails/doc/classes/SeleniumHelper.html +0 -148
  249. data/vendor/plugins/selenium-on-rails/doc/classes/SeleniumOnRails.html +0 -126
  250. data/vendor/plugins/selenium-on-rails/doc/classes/SeleniumOnRails/FixtureLoader.html +0 -231
  251. data/vendor/plugins/selenium-on-rails/doc/classes/SeleniumOnRails/PartialsSupport.html +0 -195
  252. data/vendor/plugins/selenium-on-rails/doc/classes/SeleniumOnRails/Paths.html +0 -295
  253. data/vendor/plugins/selenium-on-rails/doc/classes/SeleniumOnRails/RSelenese.html +0 -219
  254. data/vendor/plugins/selenium-on-rails/doc/classes/SeleniumOnRails/Renderer.html +0 -156
  255. data/vendor/plugins/selenium-on-rails/doc/classes/SeleniumOnRails/Selenese.html +0 -179
  256. data/vendor/plugins/selenium-on-rails/doc/classes/SeleniumOnRails/SuiteRenderer.html +0 -223
  257. data/vendor/plugins/selenium-on-rails/doc/classes/SeleniumOnRails/TestBuilder.html +0 -441
  258. data/vendor/plugins/selenium-on-rails/doc/classes/SeleniumOnRails/TestBuilderAccessors.html +0 -3098
  259. data/vendor/plugins/selenium-on-rails/doc/classes/SeleniumOnRails/TestBuilderActions.html +0 -2080
  260. data/vendor/plugins/selenium-on-rails/doc/classes/SeleniumOnRails/TestBuilderUserAccessors.html +0 -116
  261. data/vendor/plugins/selenium-on-rails/doc/classes/SeleniumOnRails/TestBuilderUserActions.html +0 -116
  262. data/vendor/plugins/selenium-on-rails/doc/classes/SeleniumOnRailsConfig.html +0 -150
  263. data/vendor/plugins/selenium-on-rails/doc/files/CHANGELOG.html +0 -422
  264. data/vendor/plugins/selenium-on-rails/doc/files/README.html +0 -321
  265. data/vendor/plugins/selenium-on-rails/doc/files/lib/controllers/selenium_controller_rb.html +0 -108
  266. data/vendor/plugins/selenium-on-rails/doc/files/lib/selenium_helper_rb.html +0 -101
  267. data/vendor/plugins/selenium-on-rails/doc/files/lib/selenium_on_rails/acceptance_test_runner_rb.html +0 -222
  268. data/vendor/plugins/selenium-on-rails/doc/files/lib/selenium_on_rails/fixture_loader_rb.html +0 -109
  269. data/vendor/plugins/selenium-on-rails/doc/files/lib/selenium_on_rails/partials_support_rb.html +0 -111
  270. data/vendor/plugins/selenium-on-rails/doc/files/lib/selenium_on_rails/paths_rb.html +0 -101
  271. data/vendor/plugins/selenium-on-rails/doc/files/lib/selenium_on_rails/renderer_rb.html +0 -101
  272. data/vendor/plugins/selenium-on-rails/doc/files/lib/selenium_on_rails/rselenese_rb.html +0 -118
  273. data/vendor/plugins/selenium-on-rails/doc/files/lib/selenium_on_rails/selenese_rb.html +0 -101
  274. data/vendor/plugins/selenium-on-rails/doc/files/lib/selenium_on_rails/suite_renderer_rb.html +0 -101
  275. data/vendor/plugins/selenium-on-rails/doc/files/lib/selenium_on_rails/test_builder_accessors_rb.html +0 -114
  276. data/vendor/plugins/selenium-on-rails/doc/files/lib/selenium_on_rails/test_builder_actions_rb.html +0 -113
  277. data/vendor/plugins/selenium-on-rails/doc/files/lib/selenium_on_rails/test_builder_rb.html +0 -120
  278. data/vendor/plugins/selenium-on-rails/doc/files/lib/selenium_on_rails_config_rb.html +0 -108
  279. data/vendor/plugins/selenium-on-rails/doc/files/lib/selenium_on_rails_rb.html +0 -115
  280. data/vendor/plugins/selenium-on-rails/doc/fr_class_index.html +0 -42
  281. data/vendor/plugins/selenium-on-rails/doc/fr_file_index.html +0 -43
  282. data/vendor/plugins/selenium-on-rails/doc/fr_method_index.html +0 -182
  283. data/vendor/plugins/selenium-on-rails/doc/index.html +0 -24
  284. data/vendor/plugins/selenium-on-rails/doc/rdoc-style.css +0 -208
  285. data/vendor/plugins/selenium-on-rails/generators/selenium/USAGE +0 -19
  286. data/vendor/plugins/selenium-on-rails/generators/selenium/selenium_generator.rb +0 -50
  287. data/vendor/plugins/selenium-on-rails/generators/selenium/templates/rhtml.rhtml +0 -16
  288. data/vendor/plugins/selenium-on-rails/generators/selenium/templates/rselenese.rhtml +0 -14
  289. data/vendor/plugins/selenium-on-rails/generators/selenium/templates/selenese.rhtml +0 -11
  290. data/vendor/plugins/selenium-on-rails/init.rb +0 -15
  291. data/vendor/plugins/selenium-on-rails/lib/controllers/selenium_controller.rb +0 -122
  292. data/vendor/plugins/selenium-on-rails/lib/controllers/switch_environment_controller.rb +0 -16
  293. data/vendor/plugins/selenium-on-rails/lib/selenium_helper.rb +0 -8
  294. data/vendor/plugins/selenium-on-rails/lib/selenium_on_rails.rb +0 -11
  295. data/vendor/plugins/selenium-on-rails/lib/selenium_on_rails/acceptance_test_runner.rb +0 -215
  296. data/vendor/plugins/selenium-on-rails/lib/selenium_on_rails/fixture_loader.rb +0 -57
  297. data/vendor/plugins/selenium-on-rails/lib/selenium_on_rails/partials_support.rb +0 -36
  298. data/vendor/plugins/selenium-on-rails/lib/selenium_on_rails/paths.rb +0 -61
  299. data/vendor/plugins/selenium-on-rails/lib/selenium_on_rails/renderer.rb +0 -20
  300. data/vendor/plugins/selenium-on-rails/lib/selenium_on_rails/rselenese.rb +0 -44
  301. data/vendor/plugins/selenium-on-rails/lib/selenium_on_rails/selenese.rb +0 -87
  302. data/vendor/plugins/selenium-on-rails/lib/selenium_on_rails/suite_renderer.rb +0 -56
  303. data/vendor/plugins/selenium-on-rails/lib/selenium_on_rails/test_builder.rb +0 -116
  304. data/vendor/plugins/selenium-on-rails/lib/selenium_on_rails/test_builder_accessors.rb +0 -1002
  305. data/vendor/plugins/selenium-on-rails/lib/selenium_on_rails/test_builder_actions.rb +0 -514
  306. data/vendor/plugins/selenium-on-rails/lib/selenium_on_rails/test_builder_user_accessors.rb.example +0 -91
  307. data/vendor/plugins/selenium-on-rails/lib/selenium_on_rails/test_builder_user_actions.rb.example +0 -24
  308. data/vendor/plugins/selenium-on-rails/lib/selenium_on_rails_config.rb +0 -30
  309. data/vendor/plugins/selenium-on-rails/lib/views/layouts/layout.rhtml +0 -18
  310. data/vendor/plugins/selenium-on-rails/lib/views/record.rhtml +0 -5
  311. data/vendor/plugins/selenium-on-rails/lib/views/selenium_helper.rb +0 -9
  312. data/vendor/plugins/selenium-on-rails/lib/views/setup.rhtml +0 -67
  313. data/vendor/plugins/selenium-on-rails/lib/views/test_suite.rhtml +0 -26
  314. data/vendor/plugins/selenium-on-rails/routes.rb +0 -24
  315. data/vendor/plugins/selenium-on-rails/selenium-core/Blank.html +0 -7
  316. data/vendor/plugins/selenium-on-rails/selenium-core/InjectedRemoteRunner.html +0 -8
  317. data/vendor/plugins/selenium-on-rails/selenium-core/RemoteRunner.html +0 -110
  318. data/vendor/plugins/selenium-on-rails/selenium-core/SeleniumLog.html +0 -109
  319. data/vendor/plugins/selenium-on-rails/selenium-core/TestPrompt.html +0 -145
  320. data/vendor/plugins/selenium-on-rails/selenium-core/TestRunner-splash.html +0 -55
  321. data/vendor/plugins/selenium-on-rails/selenium-core/TestRunner.hta +0 -177
  322. data/vendor/plugins/selenium-on-rails/selenium-core/TestRunner.html +0 -177
  323. data/vendor/plugins/selenium-on-rails/selenium-core/domviewer/butmin.gif +0 -0
  324. data/vendor/plugins/selenium-on-rails/selenium-core/domviewer/butplus.gif +0 -0
  325. data/vendor/plugins/selenium-on-rails/selenium-core/domviewer/domviewer.css +0 -298
  326. data/vendor/plugins/selenium-on-rails/selenium-core/domviewer/domviewer.html +0 -16
  327. data/vendor/plugins/selenium-on-rails/selenium-core/domviewer/selenium-domviewer.js +0 -205
  328. data/vendor/plugins/selenium-on-rails/selenium-core/icons/all.png +0 -0
  329. data/vendor/plugins/selenium-on-rails/selenium-core/icons/continue.png +0 -0
  330. data/vendor/plugins/selenium-on-rails/selenium-core/icons/continue_disabled.png +0 -0
  331. data/vendor/plugins/selenium-on-rails/selenium-core/icons/pause.png +0 -0
  332. data/vendor/plugins/selenium-on-rails/selenium-core/icons/pause_disabled.png +0 -0
  333. data/vendor/plugins/selenium-on-rails/selenium-core/icons/selected.png +0 -0
  334. data/vendor/plugins/selenium-on-rails/selenium-core/icons/step.png +0 -0
  335. data/vendor/plugins/selenium-on-rails/selenium-core/icons/step_disabled.png +0 -0
  336. data/vendor/plugins/selenium-on-rails/selenium-core/iedoc-core.xml +0 -1759
  337. data/vendor/plugins/selenium-on-rails/selenium-core/iedoc.xml +0 -1800
  338. data/vendor/plugins/selenium-on-rails/selenium-core/lib/cssQuery/cssQuery-p.js +0 -6
  339. data/vendor/plugins/selenium-on-rails/selenium-core/lib/cssQuery/src/cssQuery-level2.js +0 -142
  340. data/vendor/plugins/selenium-on-rails/selenium-core/lib/cssQuery/src/cssQuery-level3.js +0 -150
  341. data/vendor/plugins/selenium-on-rails/selenium-core/lib/cssQuery/src/cssQuery-standard.js +0 -53
  342. data/vendor/plugins/selenium-on-rails/selenium-core/lib/cssQuery/src/cssQuery.js +0 -356
  343. data/vendor/plugins/selenium-on-rails/selenium-core/lib/prototype.js +0 -2006
  344. data/vendor/plugins/selenium-on-rails/selenium-core/lib/scriptaculous/builder.js +0 -101
  345. data/vendor/plugins/selenium-on-rails/selenium-core/lib/scriptaculous/controls.js +0 -815
  346. data/vendor/plugins/selenium-on-rails/selenium-core/lib/scriptaculous/dragdrop.js +0 -915
  347. data/vendor/plugins/selenium-on-rails/selenium-core/lib/scriptaculous/effects.js +0 -958
  348. data/vendor/plugins/selenium-on-rails/selenium-core/lib/scriptaculous/scriptaculous.js +0 -47
  349. data/vendor/plugins/selenium-on-rails/selenium-core/lib/scriptaculous/slider.js +0 -283
  350. data/vendor/plugins/selenium-on-rails/selenium-core/lib/scriptaculous/unittest.js +0 -383
  351. data/vendor/plugins/selenium-on-rails/selenium-core/lib/snapsie.js +0 -91
  352. data/vendor/plugins/selenium-on-rails/selenium-core/scripts/find_matching_child.js +0 -69
  353. data/vendor/plugins/selenium-on-rails/selenium-core/scripts/htmlutils.js +0 -1616
  354. data/vendor/plugins/selenium-on-rails/selenium-core/scripts/injection.html +0 -72
  355. data/vendor/plugins/selenium-on-rails/selenium-core/scripts/selenium-api.js +0 -3184
  356. data/vendor/plugins/selenium-on-rails/selenium-core/scripts/selenium-browserbot.js +0 -2300
  357. data/vendor/plugins/selenium-on-rails/selenium-core/scripts/selenium-browserdetect.js +0 -153
  358. data/vendor/plugins/selenium-on-rails/selenium-core/scripts/selenium-commandhandlers.js +0 -377
  359. data/vendor/plugins/selenium-on-rails/selenium-core/scripts/selenium-executionloop.js +0 -175
  360. data/vendor/plugins/selenium-on-rails/selenium-core/scripts/selenium-logging.js +0 -148
  361. data/vendor/plugins/selenium-on-rails/selenium-core/scripts/selenium-remoterunner.js +0 -695
  362. data/vendor/plugins/selenium-on-rails/selenium-core/scripts/selenium-testrunner.js +0 -1362
  363. data/vendor/plugins/selenium-on-rails/selenium-core/scripts/selenium-version.js +0 -5
  364. data/vendor/plugins/selenium-on-rails/selenium-core/scripts/ui-doc.html +0 -803
  365. data/vendor/plugins/selenium-on-rails/selenium-core/scripts/ui-element.js +0 -1537
  366. data/vendor/plugins/selenium-on-rails/selenium-core/scripts/ui-map-sample.js +0 -979
  367. data/vendor/plugins/selenium-on-rails/selenium-core/scripts/user-extensions.js +0 -3
  368. data/vendor/plugins/selenium-on-rails/selenium-core/scripts/user-extensions.js.sample +0 -75
  369. data/vendor/plugins/selenium-on-rails/selenium-core/scripts/xmlextras.js +0 -153
  370. data/vendor/plugins/selenium-on-rails/selenium-core/selenium-logo.png +0 -0
  371. data/vendor/plugins/selenium-on-rails/selenium-core/selenium-test.css +0 -43
  372. data/vendor/plugins/selenium-on-rails/selenium-core/selenium.css +0 -316
  373. data/vendor/plugins/selenium-on-rails/selenium-core/xpath/dom.js +0 -566
  374. data/vendor/plugins/selenium-on-rails/selenium-core/xpath/javascript-xpath-0.1.11.js +0 -2816
  375. data/vendor/plugins/selenium-on-rails/selenium-core/xpath/util.js +0 -549
  376. data/vendor/plugins/selenium-on-rails/selenium-core/xpath/xmltoken.js +0 -149
  377. data/vendor/plugins/selenium-on-rails/selenium-core/xpath/xpath.js +0 -2450
  378. data/vendor/plugins/selenium-on-rails/tasks/test_acceptance.rake +0 -8
  379. data/vendor/plugins/selenium-on-rails/test/fixtures/config.yml +0 -37
  380. data/vendor/plugins/selenium-on-rails/test/fixtures/selenium.yml +0 -27
  381. data/vendor/plugins/selenium-on-rails/test/paths_test.rb +0 -72
  382. data/vendor/plugins/selenium-on-rails/test/renderer_test.rb +0 -157
  383. data/vendor/plugins/selenium-on-rails/test/rselenese_test.rb +0 -708
  384. data/vendor/plugins/selenium-on-rails/test/selenese_test.rb +0 -242
  385. data/vendor/plugins/selenium-on-rails/test/selenium_controller_test.rb +0 -67
  386. data/vendor/plugins/selenium-on-rails/test/selenium_on_rails_config_test.rb +0 -43
  387. data/vendor/plugins/selenium-on-rails/test/selenium_support_test.rb +0 -35
  388. data/vendor/plugins/selenium-on-rails/test/setup_test.rb +0 -31
  389. data/vendor/plugins/selenium-on-rails/test/suite_renderer_test.rb +0 -109
  390. data/vendor/plugins/selenium-on-rails/test/switch_environment_controller_test.rb +0 -17
  391. data/vendor/plugins/selenium-on-rails/test/test_builder_functions_authortest.rb +0 -51
  392. data/vendor/plugins/selenium-on-rails/test/test_helper.rb +0 -101
  393. data/vendor/plugins/selenium-on-rails/test_data/_partial.rsel +0 -1
  394. data/vendor/plugins/selenium-on-rails/test_data/own_layout.html +0 -12
  395. data/vendor/plugins/selenium-on-rails/test_data/partials/_html.html +0 -6
  396. data/vendor/plugins/selenium-on-rails/test_data/partials/_nesting.rsel +0 -2
  397. data/vendor/plugins/selenium-on-rails/test_data/partials/_rhtml.rhtml +0 -6
  398. data/vendor/plugins/selenium-on-rails/test_data/partials/_rsel.rsel +0 -1
  399. data/vendor/plugins/selenium-on-rails/test_data/partials/_sel.sel +0 -5
  400. data/vendor/plugins/selenium-on-rails/test_data/partials/all_partials.rsel +0 -5
  401. data/vendor/plugins/selenium-on-rails/test_data/rhtml.rhtml +0 -7
  402. data/vendor/plugins/selenium-on-rails/test_data/rselenese.rsel +0 -8
  403. data/vendor/plugins/selenium-on-rails/test_data/selenese.sel +0 -7
  404. data/vendor/plugins/selenium-on-rails/test_data/suite_one/subsuite/suite_one_subsuite_testcase.sel +0 -1
  405. data/vendor/plugins/selenium-on-rails/test_data/suite_one/suite_one_testcase1.sel +0 -1
  406. data/vendor/plugins/selenium-on-rails/test_data/suite_one/suite_one_testcase2.sel +0 -1
  407. data/vendor/plugins/selenium-on-rails/test_data/suite_two/suite_two_testcase.sel +0 -1
@@ -1,149 +0,0 @@
1
- // Copyright 2006 Google Inc.
2
- // All Rights Reserved
3
- //
4
- // Defines regular expression patterns to extract XML tokens from string.
5
- // See <http://www.w3.org/TR/REC-xml/#sec-common-syn>,
6
- // <http://www.w3.org/TR/xml11/#sec-common-syn> and
7
- // <http://www.w3.org/TR/REC-xml-names/#NT-NCName> for the specifications.
8
- //
9
- // Author: Junji Takagi <jtakagi@google.com>
10
-
11
- // Detect whether RegExp supports Unicode characters or not.
12
-
13
- var REGEXP_UNICODE = function() {
14
- var tests = [' ', '\u0120', -1, // Konquerer 3.4.0 fails here.
15
- '!', '\u0120', -1,
16
- '\u0120', '\u0120', 0,
17
- '\u0121', '\u0120', -1,
18
- '\u0121', '\u0120|\u0121', 0,
19
- '\u0122', '\u0120|\u0121', -1,
20
- '\u0120', '[\u0120]', 0, // Safari 2.0.3 fails here.
21
- '\u0121', '[\u0120]', -1,
22
- '\u0121', '[\u0120\u0121]', 0, // Safari 2.0.3 fails here.
23
- '\u0122', '[\u0120\u0121]', -1,
24
- '\u0121', '[\u0120-\u0121]', 0, // Safari 2.0.3 fails here.
25
- '\u0122', '[\u0120-\u0121]', -1];
26
- for (var i = 0; i < tests.length; i += 3) {
27
- if (tests[i].search(new RegExp(tests[i + 1])) != tests[i + 2]) {
28
- return false;
29
- }
30
- }
31
- return true;
32
- }();
33
-
34
- // Common tokens in XML 1.0 and XML 1.1.
35
-
36
- var XML_S = '[ \t\r\n]+';
37
- var XML_EQ = '(' + XML_S + ')?=(' + XML_S + ')?';
38
- var XML_CHAR_REF = '&#[0-9]+;|&#x[0-9a-fA-F]+;';
39
-
40
- // XML 1.0 tokens.
41
-
42
- var XML10_VERSION_INFO = XML_S + 'version' + XML_EQ + '("1\\.0"|' + "'1\\.0')";
43
- var XML10_BASE_CHAR = (REGEXP_UNICODE) ?
44
- '\u0041-\u005a\u0061-\u007a\u00c0-\u00d6\u00d8-\u00f6\u00f8-\u00ff' +
45
- '\u0100-\u0131\u0134-\u013e\u0141-\u0148\u014a-\u017e\u0180-\u01c3' +
46
- '\u01cd-\u01f0\u01f4-\u01f5\u01fa-\u0217\u0250-\u02a8\u02bb-\u02c1\u0386' +
47
- '\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03ce\u03d0-\u03d6\u03da\u03dc' +
48
- '\u03de\u03e0\u03e2-\u03f3\u0401-\u040c\u040e-\u044f\u0451-\u045c' +
49
- '\u045e-\u0481\u0490-\u04c4\u04c7-\u04c8\u04cb-\u04cc\u04d0-\u04eb' +
50
- '\u04ee-\u04f5\u04f8-\u04f9\u0531-\u0556\u0559\u0561-\u0586\u05d0-\u05ea' +
51
- '\u05f0-\u05f2\u0621-\u063a\u0641-\u064a\u0671-\u06b7\u06ba-\u06be' +
52
- '\u06c0-\u06ce\u06d0-\u06d3\u06d5\u06e5-\u06e6\u0905-\u0939\u093d' +
53
- '\u0958-\u0961\u0985-\u098c\u098f-\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2' +
54
- '\u09b6-\u09b9\u09dc-\u09dd\u09df-\u09e1\u09f0-\u09f1\u0a05-\u0a0a' +
55
- '\u0a0f-\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32-\u0a33\u0a35-\u0a36' +
56
- '\u0a38-\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8b\u0a8d' +
57
- '\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2-\u0ab3\u0ab5-\u0ab9' +
58
- '\u0abd\u0ae0\u0b05-\u0b0c\u0b0f-\u0b10\u0b13-\u0b28\u0b2a-\u0b30' +
59
- '\u0b32-\u0b33\u0b36-\u0b39\u0b3d\u0b5c-\u0b5d\u0b5f-\u0b61\u0b85-\u0b8a' +
60
- '\u0b8e-\u0b90\u0b92-\u0b95\u0b99-\u0b9a\u0b9c\u0b9e-\u0b9f\u0ba3-\u0ba4' +
61
- '\u0ba8-\u0baa\u0bae-\u0bb5\u0bb7-\u0bb9\u0c05-\u0c0c\u0c0e-\u0c10' +
62
- '\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c60-\u0c61\u0c85-\u0c8c' +
63
- '\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cde\u0ce0-\u0ce1' +
64
- '\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d28\u0d2a-\u0d39\u0d60-\u0d61' +
65
- '\u0e01-\u0e2e\u0e30\u0e32-\u0e33\u0e40-\u0e45\u0e81-\u0e82\u0e84' +
66
- '\u0e87-\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5' +
67
- '\u0ea7\u0eaa-\u0eab\u0ead-\u0eae\u0eb0\u0eb2-\u0eb3\u0ebd\u0ec0-\u0ec4' +
68
- '\u0f40-\u0f47\u0f49-\u0f69\u10a0-\u10c5\u10d0-\u10f6\u1100\u1102-\u1103' +
69
- '\u1105-\u1107\u1109\u110b-\u110c\u110e-\u1112\u113c\u113e\u1140\u114c' +
70
- '\u114e\u1150\u1154-\u1155\u1159\u115f-\u1161\u1163\u1165\u1167\u1169' +
71
- '\u116d-\u116e\u1172-\u1173\u1175\u119e\u11a8\u11ab\u11ae-\u11af' +
72
- '\u11b7-\u11b8\u11ba\u11bc-\u11c2\u11eb\u11f0\u11f9\u1e00-\u1e9b' +
73
- '\u1ea0-\u1ef9\u1f00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d' +
74
- '\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc' +
75
- '\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec' +
76
- '\u1ff2-\u1ff4\u1ff6-\u1ffc\u2126\u212a-\u212b\u212e\u2180-\u2182' +
77
- '\u3041-\u3094\u30a1-\u30fa\u3105-\u312c\uac00-\ud7a3' :
78
- 'A-Za-z';
79
- var XML10_IDEOGRAPHIC = (REGEXP_UNICODE) ?
80
- '\u4e00-\u9fa5\u3007\u3021-\u3029' :
81
- '';
82
- var XML10_COMBINING_CHAR = (REGEXP_UNICODE) ?
83
- '\u0300-\u0345\u0360-\u0361\u0483-\u0486\u0591-\u05a1\u05a3-\u05b9' +
84
- '\u05bb-\u05bd\u05bf\u05c1-\u05c2\u05c4\u064b-\u0652\u0670\u06d6-\u06dc' +
85
- '\u06dd-\u06df\u06e0-\u06e4\u06e7-\u06e8\u06ea-\u06ed\u0901-\u0903\u093c' +
86
- '\u093e-\u094c\u094d\u0951-\u0954\u0962-\u0963\u0981-\u0983\u09bc\u09be' +
87
- '\u09bf\u09c0-\u09c4\u09c7-\u09c8\u09cb-\u09cd\u09d7\u09e2-\u09e3\u0a02' +
88
- '\u0a3c\u0a3e\u0a3f\u0a40-\u0a42\u0a47-\u0a48\u0a4b-\u0a4d\u0a70-\u0a71' +
89
- '\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0b01-\u0b03' +
90
- '\u0b3c\u0b3e-\u0b43\u0b47-\u0b48\u0b4b-\u0b4d\u0b56-\u0b57\u0b82-\u0b83' +
91
- '\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0c01-\u0c03\u0c3e-\u0c44' +
92
- '\u0c46-\u0c48\u0c4a-\u0c4d\u0c55-\u0c56\u0c82-\u0c83\u0cbe-\u0cc4' +
93
- '\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5-\u0cd6\u0d02-\u0d03\u0d3e-\u0d43' +
94
- '\u0d46-\u0d48\u0d4a-\u0d4d\u0d57\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1' +
95
- '\u0eb4-\u0eb9\u0ebb-\u0ebc\u0ec8-\u0ecd\u0f18-\u0f19\u0f35\u0f37\u0f39' +
96
- '\u0f3e\u0f3f\u0f71-\u0f84\u0f86-\u0f8b\u0f90-\u0f95\u0f97\u0f99-\u0fad' +
97
- '\u0fb1-\u0fb7\u0fb9\u20d0-\u20dc\u20e1\u302a-\u302f\u3099\u309a' :
98
- '';
99
- var XML10_DIGIT = (REGEXP_UNICODE) ?
100
- '\u0030-\u0039\u0660-\u0669\u06f0-\u06f9\u0966-\u096f\u09e6-\u09ef' +
101
- '\u0a66-\u0a6f\u0ae6-\u0aef\u0b66-\u0b6f\u0be7-\u0bef\u0c66-\u0c6f' +
102
- '\u0ce6-\u0cef\u0d66-\u0d6f\u0e50-\u0e59\u0ed0-\u0ed9\u0f20-\u0f29' :
103
- '0-9';
104
- var XML10_EXTENDER = (REGEXP_UNICODE) ?
105
- '\u00b7\u02d0\u02d1\u0387\u0640\u0e46\u0ec6\u3005\u3031-\u3035' +
106
- '\u309d-\u309e\u30fc-\u30fe' :
107
- '';
108
- var XML10_LETTER = XML10_BASE_CHAR + XML10_IDEOGRAPHIC;
109
- var XML10_NAME_CHAR = XML10_LETTER + XML10_DIGIT + '\\._:' +
110
- XML10_COMBINING_CHAR + XML10_EXTENDER + '-';
111
- var XML10_NAME = '[' + XML10_LETTER + '_:][' + XML10_NAME_CHAR + ']*';
112
-
113
- var XML10_ENTITY_REF = '&' + XML10_NAME + ';';
114
- var XML10_REFERENCE = XML10_ENTITY_REF + '|' + XML_CHAR_REF;
115
- var XML10_ATT_VALUE = '"(([^<&"]|' + XML10_REFERENCE + ')*)"|' +
116
- "'(([^<&']|" + XML10_REFERENCE + ")*)'";
117
- var XML10_ATTRIBUTE =
118
- '(' + XML10_NAME + ')' + XML_EQ + '(' + XML10_ATT_VALUE + ')';
119
-
120
- // XML 1.1 tokens.
121
- // TODO(jtakagi): NameStartChar also includes \u10000-\ueffff.
122
- // ECMAScript Language Specifiction defines UnicodeEscapeSequence as
123
- // "\u HexDigit HexDigit HexDigit HexDigit" and we may need to use
124
- // surrogate pairs, but any browser doesn't support surrogate paris in
125
- // character classes of regular expression, so avoid including them for now.
126
-
127
- var XML11_VERSION_INFO = XML_S + 'version' + XML_EQ + '("1\\.1"|' + "'1\\.1')";
128
- var XML11_NAME_START_CHAR = (REGEXP_UNICODE) ?
129
- ':A-Z_a-z\u00c0-\u00d6\u00d8-\u00f6\u00f8-\u02ff\u0370-\u037d' +
130
- '\u037f-\u1fff\u200c-\u200d\u2070-\u218f\u2c00-\u2fef\u3001-\ud7ff' +
131
- '\uf900-\ufdcf\ufdf0-\ufffd' :
132
- ':A-Z_a-z';
133
- var XML11_NAME_CHAR = XML11_NAME_START_CHAR +
134
- ((REGEXP_UNICODE) ? '\\.0-9\u00b7\u0300-\u036f\u203f-\u2040-' : '\\.0-9-');
135
- var XML11_NAME = '[' + XML11_NAME_START_CHAR + '][' + XML11_NAME_CHAR + ']*';
136
-
137
- var XML11_ENTITY_REF = '&' + XML11_NAME + ';';
138
- var XML11_REFERENCE = XML11_ENTITY_REF + '|' + XML_CHAR_REF;
139
- var XML11_ATT_VALUE = '"(([^<&"]|' + XML11_REFERENCE + ')*)"|' +
140
- "'(([^<&']|" + XML11_REFERENCE + ")*)'";
141
- var XML11_ATTRIBUTE =
142
- '(' + XML11_NAME + ')' + XML_EQ + '(' + XML11_ATT_VALUE + ')';
143
-
144
- // XML Namespace tokens.
145
- // Used in XML parser and XPath parser.
146
-
147
- var XML_NC_NAME_CHAR = XML10_LETTER + XML10_DIGIT + '\\._' +
148
- XML10_COMBINING_CHAR + XML10_EXTENDER + '-';
149
- var XML_NC_NAME = '[' + XML10_LETTER + '_][' + XML_NC_NAME_CHAR + ']*';
@@ -1,2450 +0,0 @@
1
- // Copyright 2005 Google Inc.
2
- // All Rights Reserved
3
- //
4
- // An XPath parser and evaluator written in JavaScript. The
5
- // implementation is complete except for functions handling
6
- // namespaces.
7
- //
8
- // Reference: [XPATH] XPath Specification
9
- // <http://www.w3.org/TR/1999/REC-xpath-19991116>.
10
- //
11
- //
12
- // The API of the parser has several parts:
13
- //
14
- // 1. The parser function xpathParse() that takes a string and returns
15
- // an expession object.
16
- //
17
- // 2. The expression object that has an evaluate() method to evaluate the
18
- // XPath expression it represents. (It is actually a hierarchy of
19
- // objects that resembles the parse tree, but an application will call
20
- // evaluate() only on the top node of this hierarchy.)
21
- //
22
- // 3. The context object that is passed as an argument to the evaluate()
23
- // method, which represents the DOM context in which the expression is
24
- // evaluated.
25
- //
26
- // 4. The value object that is returned from evaluate() and represents
27
- // values of the different types that are defined by XPath (number,
28
- // string, boolean, and node-set), and allows to convert between them.
29
- //
30
- // These parts are near the top of the file, the functions and data
31
- // that are used internally follow after them.
32
- //
33
- //
34
- // Author: Steffen Meschkat <mesch@google.com>
35
-
36
-
37
- // The entry point for the parser.
38
- //
39
- // @param expr a string that contains an XPath expression.
40
- // @return an expression object that can be evaluated with an
41
- // expression context.
42
-
43
- function xpathParse(expr) {
44
- xpathLog('parse ' + expr);
45
- xpathParseInit();
46
-
47
- var cached = xpathCacheLookup(expr);
48
- if (cached) {
49
- xpathLog(' ... cached');
50
- return cached;
51
- }
52
-
53
- // Optimize for a few common cases: simple attribute node tests
54
- // (@id), simple element node tests (page), variable references
55
- // ($address), numbers (4), multi-step path expressions where each
56
- // step is a plain element node test
57
- // (page/overlay/locations/location).
58
-
59
- if (expr.match(/^(\$|@)?\w+$/i)) {
60
- var ret = makeSimpleExpr(expr);
61
- xpathParseCache[expr] = ret;
62
- xpathLog(' ... simple');
63
- return ret;
64
- }
65
-
66
- if (expr.match(/^\w+(\/\w+)*$/i)) {
67
- var ret = makeSimpleExpr2(expr);
68
- xpathParseCache[expr] = ret;
69
- xpathLog(' ... simple 2');
70
- return ret;
71
- }
72
-
73
- var cachekey = expr; // expr is modified during parse
74
-
75
- var stack = [];
76
- var ahead = null;
77
- var previous = null;
78
- var done = false;
79
-
80
- var parse_count = 0;
81
- var lexer_count = 0;
82
- var reduce_count = 0;
83
-
84
- while (!done) {
85
- parse_count++;
86
- expr = expr.replace(/^\s*/, '');
87
- previous = ahead;
88
- ahead = null;
89
-
90
- var rule = null;
91
- var match = '';
92
- for (var i = 0; i < xpathTokenRules.length; ++i) {
93
- var result = xpathTokenRules[i].re.exec(expr);
94
- lexer_count++;
95
- if (result && result.length > 0 && result[0].length > match.length) {
96
- rule = xpathTokenRules[i];
97
- match = result[0];
98
- break;
99
- }
100
- }
101
-
102
- // Special case: allow operator keywords to be element and
103
- // variable names.
104
-
105
- // NOTE(mesch): The parser resolves conflicts by looking ahead,
106
- // and this is the only case where we look back to
107
- // disambiguate. So this is indeed something different, and
108
- // looking back is usually done in the lexer (via states in the
109
- // general case, called "start conditions" in flex(1)). Also,the
110
- // conflict resolution in the parser is not as robust as it could
111
- // be, so I'd like to keep as much off the parser as possible (all
112
- // these precedence values should be computed from the grammar
113
- // rules and possibly associativity declarations, as in bison(1),
114
- // and not explicitly set.
115
-
116
- if (rule &&
117
- (rule == TOK_DIV ||
118
- rule == TOK_MOD ||
119
- rule == TOK_AND ||
120
- rule == TOK_OR) &&
121
- (!previous ||
122
- previous.tag == TOK_AT ||
123
- previous.tag == TOK_DSLASH ||
124
- previous.tag == TOK_SLASH ||
125
- previous.tag == TOK_AXIS ||
126
- previous.tag == TOK_DOLLAR)) {
127
- rule = TOK_QNAME;
128
- }
129
-
130
- if (rule) {
131
- expr = expr.substr(match.length);
132
- xpathLog('token: ' + match + ' -- ' + rule.label);
133
- ahead = {
134
- tag: rule,
135
- match: match,
136
- prec: rule.prec ? rule.prec : 0, // || 0 is removed by the compiler
137
- expr: makeTokenExpr(match)
138
- };
139
-
140
- } else {
141
- xpathLog('DONE');
142
- done = true;
143
- }
144
-
145
- while (xpathReduce(stack, ahead)) {
146
- reduce_count++;
147
- xpathLog('stack: ' + stackToString(stack));
148
- }
149
- }
150
-
151
- xpathLog('stack: ' + stackToString(stack));
152
-
153
- // DGF any valid XPath should "reduce" to a single Expr token
154
- if (stack.length != 1) {
155
- throw 'XPath parse error ' + cachekey + ':\n' + stackToString(stack);
156
- }
157
-
158
- var result = stack[0].expr;
159
- xpathParseCache[cachekey] = result;
160
-
161
- xpathLog('XPath parse: ' + parse_count + ' / ' +
162
- lexer_count + ' / ' + reduce_count);
163
-
164
- return result;
165
- }
166
-
167
- var xpathParseCache = {};
168
-
169
- function xpathCacheLookup(expr) {
170
- return xpathParseCache[expr];
171
- }
172
-
173
- /*DGF xpathReduce is where the magic happens in this parser.
174
- Skim down to the bottom of this file to find the table of
175
- grammatical rules and precedence numbers, "The productions of the grammar".
176
-
177
- The idea here
178
- is that we want to take a stack of tokens and apply
179
- grammatical rules to them, "reducing" them to higher-level
180
- tokens. Ultimately, any valid XPath should reduce to exactly one
181
- "Expr" token.
182
-
183
- Reduce too early or too late and you'll have two tokens that can't reduce
184
- to single Expr. For example, you may hastily reduce a qname that
185
- should name a function, incorrectly treating it as a tag name.
186
- Or you may reduce too late, accidentally reducing the last part of the
187
- XPath into a top-level "Expr" that won't reduce with earlier parts of
188
- the XPath.
189
-
190
- A "cand" is a grammatical rule candidate, with a given precedence
191
- number. "ahead" is the upcoming token, which also has a precedence
192
- number. If the token has a higher precedence number than
193
- the rule candidate, we'll "shift" the token onto the token stack,
194
- instead of immediately applying the rule candidate.
195
-
196
- Some tokens have left associativity, in which case we shift when they
197
- have LOWER precedence than the candidate.
198
- */
199
- function xpathReduce(stack, ahead) {
200
- var cand = null;
201
-
202
- if (stack.length > 0) {
203
- var top = stack[stack.length-1];
204
- var ruleset = xpathRules[top.tag.key];
205
-
206
- if (ruleset) {
207
- for (var i = 0; i < ruleset.length; ++i) {
208
- var rule = ruleset[i];
209
- var match = xpathMatchStack(stack, rule[1]);
210
- if (match.length) {
211
- cand = {
212
- tag: rule[0],
213
- rule: rule,
214
- match: match
215
- };
216
- cand.prec = xpathGrammarPrecedence(cand);
217
- break;
218
- }
219
- }
220
- }
221
- }
222
-
223
- var ret;
224
- if (cand && (!ahead || cand.prec > ahead.prec ||
225
- (ahead.tag.left && cand.prec >= ahead.prec))) {
226
- for (var i = 0; i < cand.match.matchlength; ++i) {
227
- stack.pop();
228
- }
229
-
230
- xpathLog('reduce ' + cand.tag.label + ' ' + cand.prec +
231
- ' ahead ' + (ahead ? ahead.tag.label + ' ' + ahead.prec +
232
- (ahead.tag.left ? ' left' : '')
233
- : ' none '));
234
-
235
- var matchexpr = mapExpr(cand.match, function(m) { return m.expr; });
236
- xpathLog('going to apply ' + cand.rule[3].toString());
237
- cand.expr = cand.rule[3].apply(null, matchexpr);
238
-
239
- stack.push(cand);
240
- ret = true;
241
-
242
- } else {
243
- if (ahead) {
244
- xpathLog('shift ' + ahead.tag.label + ' ' + ahead.prec +
245
- (ahead.tag.left ? ' left' : '') +
246
- ' over ' + (cand ? cand.tag.label + ' ' +
247
- cand.prec : ' none'));
248
- stack.push(ahead);
249
- }
250
- ret = false;
251
- }
252
- return ret;
253
- }
254
-
255
- function xpathMatchStack(stack, pattern) {
256
-
257
- // NOTE(mesch): The stack matches for variable cardinality are
258
- // greedy but don't do backtracking. This would be an issue only
259
- // with rules of the form A* A, i.e. with an element with variable
260
- // cardinality followed by the same element. Since that doesn't
261
- // occur in the grammar at hand, all matches on the stack are
262
- // unambiguous.
263
-
264
- var S = stack.length;
265
- var P = pattern.length;
266
- var p, s;
267
- var match = [];
268
- match.matchlength = 0;
269
- var ds = 0;
270
- for (p = P - 1, s = S - 1; p >= 0 && s >= 0; --p, s -= ds) {
271
- ds = 0;
272
- var qmatch = [];
273
- if (pattern[p] == Q_MM) {
274
- p -= 1;
275
- match.push(qmatch);
276
- while (s - ds >= 0 && stack[s - ds].tag == pattern[p]) {
277
- qmatch.push(stack[s - ds]);
278
- ds += 1;
279
- match.matchlength += 1;
280
- }
281
-
282
- } else if (pattern[p] == Q_01) {
283
- p -= 1;
284
- match.push(qmatch);
285
- while (s - ds >= 0 && ds < 2 && stack[s - ds].tag == pattern[p]) {
286
- qmatch.push(stack[s - ds]);
287
- ds += 1;
288
- match.matchlength += 1;
289
- }
290
-
291
- } else if (pattern[p] == Q_1M) {
292
- p -= 1;
293
- match.push(qmatch);
294
- if (stack[s].tag == pattern[p]) {
295
- while (s - ds >= 0 && stack[s - ds].tag == pattern[p]) {
296
- qmatch.push(stack[s - ds]);
297
- ds += 1;
298
- match.matchlength += 1;
299
- }
300
- } else {
301
- return [];
302
- }
303
-
304
- } else if (stack[s].tag == pattern[p]) {
305
- match.push(stack[s]);
306
- ds += 1;
307
- match.matchlength += 1;
308
-
309
- } else {
310
- return [];
311
- }
312
-
313
- reverseInplace(qmatch);
314
- qmatch.expr = mapExpr(qmatch, function(m) { return m.expr; });
315
- }
316
-
317
- reverseInplace(match);
318
-
319
- if (p == -1) {
320
- return match;
321
-
322
- } else {
323
- return [];
324
- }
325
- }
326
-
327
- function xpathTokenPrecedence(tag) {
328
- return tag.prec || 2;
329
- }
330
-
331
- function xpathGrammarPrecedence(frame) {
332
- var ret = 0;
333
-
334
- if (frame.rule) { /* normal reduce */
335
- if (frame.rule.length >= 3 && frame.rule[2] >= 0) {
336
- ret = frame.rule[2];
337
-
338
- } else {
339
- for (var i = 0; i < frame.rule[1].length; ++i) {
340
- var p = xpathTokenPrecedence(frame.rule[1][i]);
341
- ret = Math.max(ret, p);
342
- }
343
- }
344
- } else if (frame.tag) { /* TOKEN match */
345
- ret = xpathTokenPrecedence(frame.tag);
346
-
347
- } else if (frame.length) { /* Q_ match */
348
- for (var j = 0; j < frame.length; ++j) {
349
- var p = xpathGrammarPrecedence(frame[j]);
350
- ret = Math.max(ret, p);
351
- }
352
- }
353
-
354
- return ret;
355
- }
356
-
357
- function stackToString(stack) {
358
- var ret = '';
359
- for (var i = 0; i < stack.length; ++i) {
360
- if (ret) {
361
- ret += '\n';
362
- }
363
- ret += stack[i].tag.label;
364
- }
365
- return ret;
366
- }
367
-
368
-
369
- // XPath expression evaluation context. An XPath context consists of a
370
- // DOM node, a list of DOM nodes that contains this node, a number
371
- // that represents the position of the single node in the list, and a
372
- // current set of variable bindings. (See XPath spec.)
373
- //
374
- // The interface of the expression context:
375
- //
376
- // Constructor -- gets the node, its position, the node set it
377
- // belongs to, and a parent context as arguments. The parent context
378
- // is used to implement scoping rules for variables: if a variable
379
- // is not found in the current context, it is looked for in the
380
- // parent context, recursively. Except for node, all arguments have
381
- // default values: default position is 0, default node set is the
382
- // set that contains only the node, and the default parent is null.
383
- //
384
- // Notice that position starts at 0 at the outside interface;
385
- // inside XPath expressions this shows up as position()=1.
386
- //
387
- // clone() -- creates a new context with the current context as
388
- // parent. If passed as argument to clone(), the new context has a
389
- // different node, position, or node set. What is not passed is
390
- // inherited from the cloned context.
391
- //
392
- // setVariable(name, expr) -- binds given XPath expression to the
393
- // name.
394
- //
395
- // getVariable(name) -- what the name says.
396
- //
397
- // setNode(position) -- sets the context to the node at the given
398
- // position. Needed to implement scoping rules for variables in
399
- // XPath. (A variable is visible to all subsequent siblings, not
400
- // only to its children.)
401
- //
402
- // set/isCaseInsensitive -- specifies whether node name tests should
403
- // be case sensitive. If you're executing xpaths against a regular
404
- // HTML DOM, you probably don't want case-sensitivity, because
405
- // browsers tend to disagree about whether elements & attributes
406
- // should be upper/lower case. If you're running xpaths in an
407
- // XSLT instance, you probably DO want case sensitivity, as per the
408
- // XSL spec.
409
-
410
- function ExprContext(node, opt_position, opt_nodelist, opt_parent,
411
- opt_caseInsensitive, opt_ignoreAttributesWithoutValue,
412
- opt_returnOnFirstMatch)
413
- {
414
- this.node = node;
415
- this.position = opt_position || 0;
416
- this.nodelist = opt_nodelist || [ node ];
417
- this.variables = {};
418
- this.parent = opt_parent || null;
419
- this.caseInsensitive = opt_caseInsensitive || false;
420
- this.ignoreAttributesWithoutValue = opt_ignoreAttributesWithoutValue || false;
421
- this.returnOnFirstMatch = opt_returnOnFirstMatch || false;
422
- if (opt_parent) {
423
- this.root = opt_parent.root;
424
- } else if (this.node.nodeType == DOM_DOCUMENT_NODE) {
425
- // NOTE(mesch): DOM Spec stipulates that the ownerDocument of a
426
- // document is null. Our root, however is the document that we are
427
- // processing, so the initial context is created from its document
428
- // node, which case we must handle here explcitly.
429
- this.root = node;
430
- } else {
431
- this.root = node.ownerDocument;
432
- }
433
- }
434
-
435
- ExprContext.prototype.clone = function(opt_node, opt_position, opt_nodelist) {
436
- return new ExprContext(
437
- opt_node || this.node,
438
- typeof opt_position != 'undefined' ? opt_position : this.position,
439
- opt_nodelist || this.nodelist, this, this.caseInsensitive,
440
- this.ignoreAttributesWithoutValue, this.returnOnFirstMatch);
441
- };
442
-
443
- ExprContext.prototype.setVariable = function(name, value) {
444
- if (value instanceof StringValue || value instanceof BooleanValue ||
445
- value instanceof NumberValue || value instanceof NodeSetValue) {
446
- this.variables[name] = value;
447
- return;
448
- }
449
- if ('true' === value) {
450
- this.variables[name] = new BooleanValue(true);
451
- } else if ('false' === value) {
452
- this.variables[name] = new BooleanValue(false);
453
- } else if (TOK_NUMBER.re.test(value)) {
454
- this.variables[name] = new NumberValue(value);
455
- } else {
456
- // DGF What if it's null?
457
- this.variables[name] = new StringValue(value);
458
- }
459
- };
460
-
461
- ExprContext.prototype.getVariable = function(name) {
462
- if (typeof this.variables[name] != 'undefined') {
463
- return this.variables[name];
464
-
465
- } else if (this.parent) {
466
- return this.parent.getVariable(name);
467
-
468
- } else {
469
- return null;
470
- }
471
- };
472
-
473
- ExprContext.prototype.setNode = function(position) {
474
- this.node = this.nodelist[position];
475
- this.position = position;
476
- };
477
-
478
- ExprContext.prototype.contextSize = function() {
479
- return this.nodelist.length;
480
- };
481
-
482
- ExprContext.prototype.isCaseInsensitive = function() {
483
- return this.caseInsensitive;
484
- };
485
-
486
- ExprContext.prototype.setCaseInsensitive = function(caseInsensitive) {
487
- return this.caseInsensitive = caseInsensitive;
488
- };
489
-
490
- ExprContext.prototype.isIgnoreAttributesWithoutValue = function() {
491
- return this.ignoreAttributesWithoutValue;
492
- };
493
-
494
- ExprContext.prototype.setIgnoreAttributesWithoutValue = function(ignore) {
495
- return this.ignoreAttributesWithoutValue = ignore;
496
- };
497
-
498
- ExprContext.prototype.isReturnOnFirstMatch = function() {
499
- return this.returnOnFirstMatch;
500
- };
501
-
502
- ExprContext.prototype.setReturnOnFirstMatch = function(returnOnFirstMatch) {
503
- return this.returnOnFirstMatch = returnOnFirstMatch;
504
- };
505
-
506
- // XPath expression values. They are what XPath expressions evaluate
507
- // to. Strangely, the different value types are not specified in the
508
- // XPath syntax, but only in the semantics, so they don't show up as
509
- // nonterminals in the grammar. Yet, some expressions are required to
510
- // evaluate to particular types, and not every type can be coerced
511
- // into every other type. Although the types of XPath values are
512
- // similar to the types present in JavaScript, the type coercion rules
513
- // are a bit peculiar, so we explicitly model XPath types instead of
514
- // mapping them onto JavaScript types. (See XPath spec.)
515
- //
516
- // The four types are:
517
- //
518
- // StringValue
519
- //
520
- // NumberValue
521
- //
522
- // BooleanValue
523
- //
524
- // NodeSetValue
525
- //
526
- // The common interface of the value classes consists of methods that
527
- // implement the XPath type coercion rules:
528
- //
529
- // stringValue() -- returns the value as a JavaScript String,
530
- //
531
- // numberValue() -- returns the value as a JavaScript Number,
532
- //
533
- // booleanValue() -- returns the value as a JavaScript Boolean,
534
- //
535
- // nodeSetValue() -- returns the value as a JavaScript Array of DOM
536
- // Node objects.
537
- //
538
-
539
- function StringValue(value) {
540
- this.value = value;
541
- this.type = 'string';
542
- }
543
-
544
- StringValue.prototype.stringValue = function() {
545
- return this.value;
546
- }
547
-
548
- StringValue.prototype.booleanValue = function() {
549
- return this.value.length > 0;
550
- }
551
-
552
- StringValue.prototype.numberValue = function() {
553
- return this.value - 0;
554
- }
555
-
556
- StringValue.prototype.nodeSetValue = function() {
557
- throw this;
558
- }
559
-
560
- function BooleanValue(value) {
561
- this.value = value;
562
- this.type = 'boolean';
563
- }
564
-
565
- BooleanValue.prototype.stringValue = function() {
566
- return '' + this.value;
567
- }
568
-
569
- BooleanValue.prototype.booleanValue = function() {
570
- return this.value;
571
- }
572
-
573
- BooleanValue.prototype.numberValue = function() {
574
- return this.value ? 1 : 0;
575
- }
576
-
577
- BooleanValue.prototype.nodeSetValue = function() {
578
- throw this;
579
- }
580
-
581
- function NumberValue(value) {
582
- this.value = value;
583
- this.type = 'number';
584
- }
585
-
586
- NumberValue.prototype.stringValue = function() {
587
- return '' + this.value;
588
- }
589
-
590
- NumberValue.prototype.booleanValue = function() {
591
- return !!this.value;
592
- }
593
-
594
- NumberValue.prototype.numberValue = function() {
595
- return this.value - 0;
596
- }
597
-
598
- NumberValue.prototype.nodeSetValue = function() {
599
- throw this;
600
- }
601
-
602
- function NodeSetValue(value) {
603
- this.value = value;
604
- this.type = 'node-set';
605
- }
606
-
607
- NodeSetValue.prototype.stringValue = function() {
608
- if (this.value.length == 0) {
609
- return '';
610
- } else {
611
- return xmlValue(this.value[0]);
612
- }
613
- }
614
-
615
- NodeSetValue.prototype.booleanValue = function() {
616
- return this.value.length > 0;
617
- }
618
-
619
- NodeSetValue.prototype.numberValue = function() {
620
- return this.stringValue() - 0;
621
- }
622
-
623
- NodeSetValue.prototype.nodeSetValue = function() {
624
- return this.value;
625
- };
626
-
627
- // XPath expressions. They are used as nodes in the parse tree and
628
- // possess an evaluate() method to compute an XPath value given an XPath
629
- // context. Expressions are returned from the parser. Teh set of
630
- // expression classes closely mirrors the set of non terminal symbols
631
- // in the grammar. Every non trivial nonterminal symbol has a
632
- // corresponding expression class.
633
- //
634
- // The common expression interface consists of the following methods:
635
- //
636
- // evaluate(context) -- evaluates the expression, returns a value.
637
- //
638
- // toString() -- returns the XPath text representation of the
639
- // expression (defined in xsltdebug.js).
640
- //
641
- // parseTree(indent) -- returns a parse tree representation of the
642
- // expression (defined in xsltdebug.js).
643
-
644
- function TokenExpr(m) {
645
- this.value = m;
646
- }
647
-
648
- TokenExpr.prototype.evaluate = function() {
649
- return new StringValue(this.value);
650
- };
651
-
652
- function LocationExpr() {
653
- this.absolute = false;
654
- this.steps = [];
655
- }
656
-
657
- LocationExpr.prototype.appendStep = function(s) {
658
- var combinedStep = this._combineSteps(this.steps[this.steps.length-1], s);
659
- if (combinedStep) {
660
- this.steps[this.steps.length-1] = combinedStep;
661
- } else {
662
- this.steps.push(s);
663
- }
664
- }
665
-
666
- LocationExpr.prototype.prependStep = function(s) {
667
- var combinedStep = this._combineSteps(s, this.steps[0]);
668
- if (combinedStep) {
669
- this.steps[0] = combinedStep;
670
- } else {
671
- this.steps.unshift(s);
672
- }
673
- };
674
-
675
- // DGF try to combine two steps into one step (perf enhancement)
676
- LocationExpr.prototype._combineSteps = function(prevStep, nextStep) {
677
- if (!prevStep) return null;
678
- if (!nextStep) return null;
679
- var hasPredicates = (prevStep.predicates && prevStep.predicates.length > 0);
680
- if (prevStep.nodetest instanceof NodeTestAny && !hasPredicates) {
681
- // maybe suitable to be combined
682
- if (prevStep.axis == xpathAxis.DESCENDANT_OR_SELF) {
683
- if (nextStep.axis == xpathAxis.CHILD) {
684
- // HBC - commenting out, because this is not a valid reduction
685
- //nextStep.axis = xpathAxis.DESCENDANT;
686
- //return nextStep;
687
- } else if (nextStep.axis == xpathAxis.SELF) {
688
- nextStep.axis = xpathAxis.DESCENDANT_OR_SELF;
689
- return nextStep;
690
- }
691
- } else if (prevStep.axis == xpathAxis.DESCENDANT) {
692
- if (nextStep.axis == xpathAxis.SELF) {
693
- nextStep.axis = xpathAxis.DESCENDANT;
694
- return nextStep;
695
- }
696
- }
697
- }
698
- return null;
699
- }
700
-
701
- LocationExpr.prototype.evaluate = function(ctx) {
702
- var start;
703
- if (this.absolute) {
704
- start = ctx.root;
705
-
706
- } else {
707
- start = ctx.node;
708
- }
709
-
710
- var nodes = [];
711
- xPathStep(nodes, this.steps, 0, start, ctx);
712
- return new NodeSetValue(nodes);
713
- };
714
-
715
- function xPathStep(nodes, steps, step, input, ctx) {
716
- var s = steps[step];
717
- var ctx2 = ctx.clone(input);
718
-
719
- if (ctx.returnOnFirstMatch && !s.hasPositionalPredicate) {
720
- var nodelist = s.evaluate(ctx2).nodeSetValue();
721
- // the predicates were not processed in the last evaluate(), so that we can
722
- // process them here with the returnOnFirstMatch optimization. We do a
723
- // depth-first grab at any nodes that pass the predicate tests. There is no
724
- // way to optimize when predicates contain positional selectors, including
725
- // indexes or uses of the last() or position() functions, because they
726
- // typically require the entire nodelist for context. Process without
727
- // optimization if we encounter such selectors.
728
- var nLength = nodelist.length;
729
- var pLength = s.predicate.length;
730
- nodelistLoop:
731
- for (var i = 0; i < nLength; ++i) {
732
- var n = nodelist[i];
733
- for (var j = 0; j < pLength; ++j) {
734
- if (!s.predicate[j].evaluate(ctx.clone(n, i, nodelist)).booleanValue()) {
735
- continue nodelistLoop;
736
- }
737
- }
738
- // n survived the predicate tests!
739
- if (step == steps.length - 1) {
740
- nodes.push(n);
741
- }
742
- else {
743
- xPathStep(nodes, steps, step + 1, n, ctx);
744
- }
745
- if (nodes.length > 0) {
746
- break;
747
- }
748
- }
749
- }
750
- else {
751
- // set returnOnFirstMatch to false for the cloned ExprContext, because
752
- // behavior in StepExpr.prototype.evaluate is driven off its value. Note
753
- // that the original context may still have true for this value.
754
- ctx2.returnOnFirstMatch = false;
755
- var nodelist = s.evaluate(ctx2).nodeSetValue();
756
- for (var i = 0; i < nodelist.length; ++i) {
757
- if (step == steps.length - 1) {
758
- nodes.push(nodelist[i]);
759
- } else {
760
- xPathStep(nodes, steps, step + 1, nodelist[i], ctx);
761
- }
762
- }
763
- }
764
- }
765
-
766
- function StepExpr(axis, nodetest, opt_predicate) {
767
- this.axis = axis;
768
- this.nodetest = nodetest;
769
- this.predicate = opt_predicate || [];
770
- this.hasPositionalPredicate = false;
771
- for (var i = 0; i < this.predicate.length; ++i) {
772
- if (predicateExprHasPositionalSelector(this.predicate[i].expr)) {
773
- this.hasPositionalPredicate = true;
774
- break;
775
- }
776
- }
777
- }
778
-
779
- StepExpr.prototype.appendPredicate = function(p) {
780
- this.predicate.push(p);
781
- if (!this.hasPositionalPredicate) {
782
- this.hasPositionalPredicate = predicateExprHasPositionalSelector(p.expr);
783
- }
784
- }
785
-
786
- StepExpr.prototype.evaluate = function(ctx) {
787
- var input = ctx.node;
788
- var nodelist = [];
789
- var skipNodeTest = false;
790
-
791
- if (this.nodetest instanceof NodeTestAny) {
792
- skipNodeTest = true;
793
- }
794
-
795
- // NOTE(mesch): When this was a switch() statement, it didn't work
796
- // in Safari/2.0. Not sure why though; it resulted in the JavaScript
797
- // console output "undefined" (without any line number or so).
798
-
799
- if (this.axis == xpathAxis.ANCESTOR_OR_SELF) {
800
- nodelist.push(input);
801
- for (var n = input.parentNode; n; n = n.parentNode) {
802
- nodelist.push(n);
803
- }
804
-
805
- } else if (this.axis == xpathAxis.ANCESTOR) {
806
- for (var n = input.parentNode; n; n = n.parentNode) {
807
- nodelist.push(n);
808
- }
809
-
810
- } else if (this.axis == xpathAxis.ATTRIBUTE) {
811
- if (this.nodetest.name != undefined) {
812
- // single-attribute step
813
- if (input.attributes) {
814
- if (input.attributes instanceof Array) {
815
- // probably evaluating on document created by xmlParse()
816
- copyArray(nodelist, input.attributes);
817
- }
818
- else {
819
- if (this.nodetest.name == 'style') {
820
- var value = input.getAttribute('style');
821
- if (value && typeof(value) != 'string') {
822
- // this is the case where indexing into the attributes array
823
- // doesn't give us the attribute node in IE - we create our own
824
- // node instead
825
- nodelist.push(XNode.create(DOM_ATTRIBUTE_NODE, 'style',
826
- value.cssText, document));
827
- }
828
- else {
829
- nodelist.push(input.attributes[this.nodetest.name]);
830
- }
831
- }
832
- else {
833
- nodelist.push(input.attributes[this.nodetest.name]);
834
- }
835
- }
836
- }
837
- }
838
- else {
839
- // all-attributes step
840
- if (ctx.ignoreAttributesWithoutValue) {
841
- copyArrayIgnoringAttributesWithoutValue(nodelist, input.attributes);
842
- }
843
- else {
844
- copyArray(nodelist, input.attributes);
845
- }
846
- }
847
-
848
- } else if (this.axis == xpathAxis.CHILD) {
849
- copyArray(nodelist, input.childNodes);
850
-
851
- } else if (this.axis == xpathAxis.DESCENDANT_OR_SELF) {
852
- if (this.nodetest.evaluate(ctx).booleanValue()) {
853
- nodelist.push(input);
854
- }
855
- var tagName = xpathExtractTagNameFromNodeTest(this.nodetest);
856
- xpathCollectDescendants(nodelist, input, tagName);
857
- if (tagName) skipNodeTest = true;
858
-
859
- } else if (this.axis == xpathAxis.DESCENDANT) {
860
- var tagName = xpathExtractTagNameFromNodeTest(this.nodetest);
861
- xpathCollectDescendants(nodelist, input, tagName);
862
- if (tagName) skipNodeTest = true;
863
-
864
- } else if (this.axis == xpathAxis.FOLLOWING) {
865
- for (var n = input; n; n = n.parentNode) {
866
- for (var nn = n.nextSibling; nn; nn = nn.nextSibling) {
867
- nodelist.push(nn);
868
- xpathCollectDescendants(nodelist, nn);
869
- }
870
- }
871
-
872
- } else if (this.axis == xpathAxis.FOLLOWING_SIBLING) {
873
- for (var n = input.nextSibling; n; n = n.nextSibling) {
874
- nodelist.push(n);
875
- }
876
-
877
- } else if (this.axis == xpathAxis.NAMESPACE) {
878
- alert('not implemented: axis namespace');
879
-
880
- } else if (this.axis == xpathAxis.PARENT) {
881
- if (input.parentNode) {
882
- nodelist.push(input.parentNode);
883
- }
884
-
885
- } else if (this.axis == xpathAxis.PRECEDING) {
886
- for (var n = input; n; n = n.parentNode) {
887
- for (var nn = n.previousSibling; nn; nn = nn.previousSibling) {
888
- nodelist.push(nn);
889
- xpathCollectDescendantsReverse(nodelist, nn);
890
- }
891
- }
892
-
893
- } else if (this.axis == xpathAxis.PRECEDING_SIBLING) {
894
- for (var n = input.previousSibling; n; n = n.previousSibling) {
895
- nodelist.push(n);
896
- }
897
-
898
- } else if (this.axis == xpathAxis.SELF) {
899
- nodelist.push(input);
900
-
901
- } else {
902
- throw 'ERROR -- NO SUCH AXIS: ' + this.axis;
903
- }
904
-
905
- if (!skipNodeTest) {
906
- // process node test
907
- var nodelist0 = nodelist;
908
- nodelist = [];
909
- for (var i = 0; i < nodelist0.length; ++i) {
910
- var n = nodelist0[i];
911
- if (this.nodetest.evaluate(ctx.clone(n, i, nodelist0)).booleanValue()) {
912
- nodelist.push(n);
913
- }
914
- }
915
- }
916
-
917
- // process predicates
918
- if (!ctx.returnOnFirstMatch) {
919
- for (var i = 0; i < this.predicate.length; ++i) {
920
- var nodelist0 = nodelist;
921
- nodelist = [];
922
- for (var ii = 0; ii < nodelist0.length; ++ii) {
923
- var n = nodelist0[ii];
924
- if (this.predicate[i].evaluate(ctx.clone(n, ii, nodelist0)).booleanValue()) {
925
- nodelist.push(n);
926
- }
927
- }
928
- }
929
- }
930
-
931
- return new NodeSetValue(nodelist);
932
- };
933
-
934
- function NodeTestAny() {
935
- this.value = new BooleanValue(true);
936
- }
937
-
938
- NodeTestAny.prototype.evaluate = function(ctx) {
939
- return this.value;
940
- };
941
-
942
- function NodeTestElementOrAttribute() {}
943
-
944
- NodeTestElementOrAttribute.prototype.evaluate = function(ctx) {
945
- return new BooleanValue(
946
- ctx.node.nodeType == DOM_ELEMENT_NODE ||
947
- ctx.node.nodeType == DOM_ATTRIBUTE_NODE);
948
- }
949
-
950
- function NodeTestText() {}
951
-
952
- NodeTestText.prototype.evaluate = function(ctx) {
953
- return new BooleanValue(ctx.node.nodeType == DOM_TEXT_NODE);
954
- }
955
-
956
- function NodeTestComment() {}
957
-
958
- NodeTestComment.prototype.evaluate = function(ctx) {
959
- return new BooleanValue(ctx.node.nodeType == DOM_COMMENT_NODE);
960
- }
961
-
962
- function NodeTestPI(target) {
963
- this.target = target;
964
- }
965
-
966
- NodeTestPI.prototype.evaluate = function(ctx) {
967
- return new
968
- BooleanValue(ctx.node.nodeType == DOM_PROCESSING_INSTRUCTION_NODE &&
969
- (!this.target || ctx.node.nodeName == this.target));
970
- }
971
-
972
- function NodeTestNC(nsprefix) {
973
- this.regex = new RegExp("^" + nsprefix + ":");
974
- this.nsprefix = nsprefix;
975
- }
976
-
977
- NodeTestNC.prototype.evaluate = function(ctx) {
978
- var n = ctx.node;
979
- return new BooleanValue(this.regex.match(n.nodeName));
980
- }
981
-
982
- function NodeTestName(name) {
983
- this.name = name;
984
- this.re = new RegExp('^' + name + '$', "i");
985
- }
986
-
987
- NodeTestName.prototype.evaluate = function(ctx) {
988
- var n = ctx.node;
989
- if (ctx.caseInsensitive) {
990
- if (n.nodeName.length != this.name.length) return new BooleanValue(false);
991
- return new BooleanValue(this.re.test(n.nodeName));
992
- } else {
993
- return new BooleanValue(n.nodeName == this.name);
994
- }
995
- }
996
-
997
- function PredicateExpr(expr) {
998
- this.expr = expr;
999
- }
1000
-
1001
- PredicateExpr.prototype.evaluate = function(ctx) {
1002
- var v = this.expr.evaluate(ctx);
1003
- if (v.type == 'number') {
1004
- // NOTE(mesch): Internally, position is represented starting with
1005
- // 0, however in XPath position starts with 1. See functions
1006
- // position() and last().
1007
- return new BooleanValue(ctx.position == v.numberValue() - 1);
1008
- } else {
1009
- return new BooleanValue(v.booleanValue());
1010
- }
1011
- };
1012
-
1013
- function FunctionCallExpr(name) {
1014
- this.name = name;
1015
- this.args = [];
1016
- }
1017
-
1018
- FunctionCallExpr.prototype.appendArg = function(arg) {
1019
- this.args.push(arg);
1020
- };
1021
-
1022
- FunctionCallExpr.prototype.evaluate = function(ctx) {
1023
- var fn = '' + this.name.value;
1024
- var f = this.xpathfunctions[fn];
1025
- if (f) {
1026
- return f.call(this, ctx);
1027
- } else {
1028
- xpathLog('XPath NO SUCH FUNCTION ' + fn);
1029
- return new BooleanValue(false);
1030
- }
1031
- };
1032
-
1033
- FunctionCallExpr.prototype.xpathfunctions = {
1034
- 'last': function(ctx) {
1035
- assert(this.args.length == 0);
1036
- // NOTE(mesch): XPath position starts at 1.
1037
- return new NumberValue(ctx.contextSize());
1038
- },
1039
-
1040
- 'position': function(ctx) {
1041
- assert(this.args.length == 0);
1042
- // NOTE(mesch): XPath position starts at 1.
1043
- return new NumberValue(ctx.position + 1);
1044
- },
1045
-
1046
- 'count': function(ctx) {
1047
- assert(this.args.length == 1);
1048
- var v = this.args[0].evaluate(ctx);
1049
- return new NumberValue(v.nodeSetValue().length);
1050
- },
1051
-
1052
- 'id': function(ctx) {
1053
- assert(this.args.length == 1);
1054
- var e = this.args[0].evaluate(ctx);
1055
- var ret = [];
1056
- var ids;
1057
- if (e.type == 'node-set') {
1058
- ids = [];
1059
- var en = e.nodeSetValue();
1060
- for (var i = 0; i < en.length; ++i) {
1061
- var v = xmlValue(en[i]).split(/\s+/);
1062
- for (var ii = 0; ii < v.length; ++ii) {
1063
- ids.push(v[ii]);
1064
- }
1065
- }
1066
- } else {
1067
- ids = e.stringValue().split(/\s+/);
1068
- }
1069
- var d = ctx.root;
1070
- for (var i = 0; i < ids.length; ++i) {
1071
- var n = d.getElementById(ids[i]);
1072
- if (n) {
1073
- ret.push(n);
1074
- }
1075
- }
1076
- return new NodeSetValue(ret);
1077
- },
1078
-
1079
- 'local-name': function(ctx) {
1080
- alert('not implmented yet: XPath function local-name()');
1081
- },
1082
-
1083
- 'namespace-uri': function(ctx) {
1084
- alert('not implmented yet: XPath function namespace-uri()');
1085
- },
1086
-
1087
- 'name': function(ctx) {
1088
- assert(this.args.length == 1 || this.args.length == 0);
1089
- var n;
1090
- if (this.args.length == 0) {
1091
- n = [ ctx.node ];
1092
- } else {
1093
- n = this.args[0].evaluate(ctx).nodeSetValue();
1094
- }
1095
-
1096
- if (n.length == 0) {
1097
- return new StringValue('');
1098
- } else {
1099
- return new StringValue(n[0].nodeName);
1100
- }
1101
- },
1102
-
1103
- 'string': function(ctx) {
1104
- assert(this.args.length == 1 || this.args.length == 0);
1105
- if (this.args.length == 0) {
1106
- return new StringValue(new NodeSetValue([ ctx.node ]).stringValue());
1107
- } else {
1108
- return new StringValue(this.args[0].evaluate(ctx).stringValue());
1109
- }
1110
- },
1111
-
1112
- 'concat': function(ctx) {
1113
- var ret = '';
1114
- for (var i = 0; i < this.args.length; ++i) {
1115
- ret += this.args[i].evaluate(ctx).stringValue();
1116
- }
1117
- return new StringValue(ret);
1118
- },
1119
-
1120
- 'starts-with': function(ctx) {
1121
- assert(this.args.length == 2);
1122
- var s0 = this.args[0].evaluate(ctx).stringValue();
1123
- var s1 = this.args[1].evaluate(ctx).stringValue();
1124
- return new BooleanValue(s0.indexOf(s1) == 0);
1125
- },
1126
-
1127
- 'ends-with': function(ctx) {
1128
- assert(this.args.length == 2);
1129
- var s0 = this.args[0].evaluate(ctx).stringValue();
1130
- var s1 = this.args[1].evaluate(ctx).stringValue();
1131
- var re = new RegExp(RegExp.escape(s1) + '$');
1132
- return new BooleanValue(re.test(s0));
1133
- },
1134
-
1135
- 'contains': function(ctx) {
1136
- assert(this.args.length == 2);
1137
- var s0 = this.args[0].evaluate(ctx).stringValue();
1138
- var s1 = this.args[1].evaluate(ctx).stringValue();
1139
- return new BooleanValue(s0.indexOf(s1) != -1);
1140
- },
1141
-
1142
- 'substring-before': function(ctx) {
1143
- assert(this.args.length == 2);
1144
- var s0 = this.args[0].evaluate(ctx).stringValue();
1145
- var s1 = this.args[1].evaluate(ctx).stringValue();
1146
- var i = s0.indexOf(s1);
1147
- var ret;
1148
- if (i == -1) {
1149
- ret = '';
1150
- } else {
1151
- ret = s0.substr(0,i);
1152
- }
1153
- return new StringValue(ret);
1154
- },
1155
-
1156
- 'substring-after': function(ctx) {
1157
- assert(this.args.length == 2);
1158
- var s0 = this.args[0].evaluate(ctx).stringValue();
1159
- var s1 = this.args[1].evaluate(ctx).stringValue();
1160
- var i = s0.indexOf(s1);
1161
- var ret;
1162
- if (i == -1) {
1163
- ret = '';
1164
- } else {
1165
- ret = s0.substr(i + s1.length);
1166
- }
1167
- return new StringValue(ret);
1168
- },
1169
-
1170
- 'substring': function(ctx) {
1171
- // NOTE: XPath defines the position of the first character in a
1172
- // string to be 1, in JavaScript this is 0 ([XPATH] Section 4.2).
1173
- assert(this.args.length == 2 || this.args.length == 3);
1174
- var s0 = this.args[0].evaluate(ctx).stringValue();
1175
- var s1 = this.args[1].evaluate(ctx).numberValue();
1176
- var ret;
1177
- if (this.args.length == 2) {
1178
- var i1 = Math.max(0, Math.round(s1) - 1);
1179
- ret = s0.substr(i1);
1180
-
1181
- } else {
1182
- var s2 = this.args[2].evaluate(ctx).numberValue();
1183
- var i0 = Math.round(s1) - 1;
1184
- var i1 = Math.max(0, i0);
1185
- var i2 = Math.round(s2) - Math.max(0, -i0);
1186
- ret = s0.substr(i1, i2);
1187
- }
1188
- return new StringValue(ret);
1189
- },
1190
-
1191
- 'string-length': function(ctx) {
1192
- var s;
1193
- if (this.args.length > 0) {
1194
- s = this.args[0].evaluate(ctx).stringValue();
1195
- } else {
1196
- s = new NodeSetValue([ ctx.node ]).stringValue();
1197
- }
1198
- return new NumberValue(s.length);
1199
- },
1200
-
1201
- 'normalize-space': function(ctx) {
1202
- var s;
1203
- if (this.args.length > 0) {
1204
- s = this.args[0].evaluate(ctx).stringValue();
1205
- } else {
1206
- s = new NodeSetValue([ ctx.node ]).stringValue();
1207
- }
1208
- s = s.replace(/^\s*/,'').replace(/\s*$/,'').replace(/\s+/g, ' ');
1209
- return new StringValue(s);
1210
- },
1211
-
1212
- 'translate': function(ctx) {
1213
- assert(this.args.length == 3);
1214
- var s0 = this.args[0].evaluate(ctx).stringValue();
1215
- var s1 = this.args[1].evaluate(ctx).stringValue();
1216
- var s2 = this.args[2].evaluate(ctx).stringValue();
1217
-
1218
- for (var i = 0; i < s1.length; ++i) {
1219
- s0 = s0.replace(new RegExp(s1.charAt(i), 'g'), s2.charAt(i));
1220
- }
1221
- return new StringValue(s0);
1222
- },
1223
-
1224
- 'matches': function(ctx) {
1225
- assert(this.args.length >= 2);
1226
- var s0 = this.args[0].evaluate(ctx).stringValue();
1227
- var s1 = this.args[1].evaluate(ctx).stringValue();
1228
- if (this.args.length > 2) {
1229
- var s2 = this.args[2].evaluate(ctx).stringValue();
1230
- if (/[^mi]/.test(s2)) {
1231
- throw 'Invalid regular expression syntax: ' + s2;
1232
- }
1233
- }
1234
-
1235
- try {
1236
- var re = new RegExp(s1, s2);
1237
- }
1238
- catch (e) {
1239
- throw 'Invalid matches argument: ' + s1;
1240
- }
1241
- return new BooleanValue(re.test(s0));
1242
- },
1243
-
1244
- 'boolean': function(ctx) {
1245
- assert(this.args.length == 1);
1246
- return new BooleanValue(this.args[0].evaluate(ctx).booleanValue());
1247
- },
1248
-
1249
- 'not': function(ctx) {
1250
- assert(this.args.length == 1);
1251
- var ret = !this.args[0].evaluate(ctx).booleanValue();
1252
- return new BooleanValue(ret);
1253
- },
1254
-
1255
- 'true': function(ctx) {
1256
- assert(this.args.length == 0);
1257
- return new BooleanValue(true);
1258
- },
1259
-
1260
- 'false': function(ctx) {
1261
- assert(this.args.length == 0);
1262
- return new BooleanValue(false);
1263
- },
1264
-
1265
- 'lang': function(ctx) {
1266
- assert(this.args.length == 1);
1267
- var lang = this.args[0].evaluate(ctx).stringValue();
1268
- var xmllang;
1269
- var n = ctx.node;
1270
- while (n && n != n.parentNode /* just in case ... */) {
1271
- xmllang = n.getAttribute('xml:lang');
1272
- if (xmllang) {
1273
- break;
1274
- }
1275
- n = n.parentNode;
1276
- }
1277
- if (!xmllang) {
1278
- return new BooleanValue(false);
1279
- } else {
1280
- var re = new RegExp('^' + lang + '$', 'i');
1281
- return new BooleanValue(xmllang.match(re) ||
1282
- xmllang.replace(/_.*$/,'').match(re));
1283
- }
1284
- },
1285
-
1286
- 'number': function(ctx) {
1287
- assert(this.args.length == 1 || this.args.length == 0);
1288
-
1289
- if (this.args.length == 1) {
1290
- return new NumberValue(this.args[0].evaluate(ctx).numberValue());
1291
- } else {
1292
- return new NumberValue(new NodeSetValue([ ctx.node ]).numberValue());
1293
- }
1294
- },
1295
-
1296
- 'sum': function(ctx) {
1297
- assert(this.args.length == 1);
1298
- var n = this.args[0].evaluate(ctx).nodeSetValue();
1299
- var sum = 0;
1300
- for (var i = 0; i < n.length; ++i) {
1301
- sum += xmlValue(n[i]) - 0;
1302
- }
1303
- return new NumberValue(sum);
1304
- },
1305
-
1306
- 'floor': function(ctx) {
1307
- assert(this.args.length == 1);
1308
- var num = this.args[0].evaluate(ctx).numberValue();
1309
- return new NumberValue(Math.floor(num));
1310
- },
1311
-
1312
- 'ceiling': function(ctx) {
1313
- assert(this.args.length == 1);
1314
- var num = this.args[0].evaluate(ctx).numberValue();
1315
- return new NumberValue(Math.ceil(num));
1316
- },
1317
-
1318
- 'round': function(ctx) {
1319
- assert(this.args.length == 1);
1320
- var num = this.args[0].evaluate(ctx).numberValue();
1321
- return new NumberValue(Math.round(num));
1322
- },
1323
-
1324
- // TODO(mesch): The following functions are custom. There is a
1325
- // standard that defines how to add functions, which should be
1326
- // applied here.
1327
-
1328
- 'ext-join': function(ctx) {
1329
- assert(this.args.length == 2);
1330
- var nodes = this.args[0].evaluate(ctx).nodeSetValue();
1331
- var delim = this.args[1].evaluate(ctx).stringValue();
1332
- var ret = '';
1333
- for (var i = 0; i < nodes.length; ++i) {
1334
- if (ret) {
1335
- ret += delim;
1336
- }
1337
- ret += xmlValue(nodes[i]);
1338
- }
1339
- return new StringValue(ret);
1340
- },
1341
-
1342
- // ext-if() evaluates and returns its second argument, if the
1343
- // boolean value of its first argument is true, otherwise it
1344
- // evaluates and returns its third argument.
1345
-
1346
- 'ext-if': function(ctx) {
1347
- assert(this.args.length == 3);
1348
- if (this.args[0].evaluate(ctx).booleanValue()) {
1349
- return this.args[1].evaluate(ctx);
1350
- } else {
1351
- return this.args[2].evaluate(ctx);
1352
- }
1353
- },
1354
-
1355
- // ext-cardinal() evaluates its single argument as a number, and
1356
- // returns the current node that many times. It can be used in the
1357
- // select attribute to iterate over an integer range.
1358
-
1359
- 'ext-cardinal': function(ctx) {
1360
- assert(this.args.length >= 1);
1361
- var c = this.args[0].evaluate(ctx).numberValue();
1362
- var ret = [];
1363
- for (var i = 0; i < c; ++i) {
1364
- ret.push(ctx.node);
1365
- }
1366
- return new NodeSetValue(ret);
1367
- }
1368
- };
1369
-
1370
- function UnionExpr(expr1, expr2) {
1371
- this.expr1 = expr1;
1372
- this.expr2 = expr2;
1373
- }
1374
-
1375
- UnionExpr.prototype.evaluate = function(ctx) {
1376
- var nodes1 = this.expr1.evaluate(ctx).nodeSetValue();
1377
- var nodes2 = this.expr2.evaluate(ctx).nodeSetValue();
1378
- var I1 = nodes1.length;
1379
- for (var i2 = 0; i2 < nodes2.length; ++i2) {
1380
- var n = nodes2[i2];
1381
- var inBoth = false;
1382
- for (var i1 = 0; i1 < I1; ++i1) {
1383
- if (nodes1[i1] == n) {
1384
- inBoth = true;
1385
- i1 = I1; // break inner loop
1386
- }
1387
- }
1388
- if (!inBoth) {
1389
- nodes1.push(n);
1390
- }
1391
- }
1392
- return new NodeSetValue(nodes1);
1393
- };
1394
-
1395
- function PathExpr(filter, rel) {
1396
- this.filter = filter;
1397
- this.rel = rel;
1398
- }
1399
-
1400
- PathExpr.prototype.evaluate = function(ctx) {
1401
- // the filter expression should be evaluated in its entirety with no
1402
- // optimization, as we can't backtrack to it after having moved on to
1403
- // evaluating the relative location path
1404
- var flag = ctx.returnOnFirstMatch;
1405
- ctx.setReturnOnFirstMatch(false);
1406
- var nodes = this.filter.evaluate(ctx).nodeSetValue();
1407
- ctx.setReturnOnFirstMatch(flag);
1408
-
1409
- var nodes1 = [];
1410
- if (ctx.returnOnFirstMatch) {
1411
- for (var i = 0; i < nodes.length; ++i) {
1412
- nodes1 = this.rel.evaluate(ctx.clone(nodes[i], i, nodes)).nodeSetValue();
1413
- if (nodes1.length > 0) {
1414
- break;
1415
- }
1416
- }
1417
- return new NodeSetValue(nodes1);
1418
- }
1419
- else {
1420
- for (var i = 0; i < nodes.length; ++i) {
1421
- var nodes0 = this.rel.evaluate(ctx.clone(nodes[i], i, nodes)).nodeSetValue();
1422
- for (var ii = 0; ii < nodes0.length; ++ii) {
1423
- nodes1.push(nodes0[ii]);
1424
- }
1425
- }
1426
- return new NodeSetValue(nodes1);
1427
- }
1428
- };
1429
-
1430
- function FilterExpr(expr, predicate) {
1431
- this.expr = expr;
1432
- this.predicate = predicate;
1433
- }
1434
-
1435
- FilterExpr.prototype.evaluate = function(ctx) {
1436
- var nodes = this.expr.evaluate(ctx).nodeSetValue();
1437
- for (var i = 0; i < this.predicate.length; ++i) {
1438
- var nodes0 = nodes;
1439
- nodes = [];
1440
- for (var j = 0; j < nodes0.length; ++j) {
1441
- var n = nodes0[j];
1442
- if (this.predicate[i].evaluate(ctx.clone(n, j, nodes0)).booleanValue()) {
1443
- nodes.push(n);
1444
- }
1445
- }
1446
- }
1447
-
1448
- return new NodeSetValue(nodes);
1449
- }
1450
-
1451
- function UnaryMinusExpr(expr) {
1452
- this.expr = expr;
1453
- }
1454
-
1455
- UnaryMinusExpr.prototype.evaluate = function(ctx) {
1456
- return new NumberValue(-this.expr.evaluate(ctx).numberValue());
1457
- };
1458
-
1459
- function BinaryExpr(expr1, op, expr2) {
1460
- this.expr1 = expr1;
1461
- this.expr2 = expr2;
1462
- this.op = op;
1463
- }
1464
-
1465
- BinaryExpr.prototype.evaluate = function(ctx) {
1466
- var ret;
1467
- switch (this.op.value) {
1468
- case 'or':
1469
- ret = new BooleanValue(this.expr1.evaluate(ctx).booleanValue() ||
1470
- this.expr2.evaluate(ctx).booleanValue());
1471
- break;
1472
-
1473
- case 'and':
1474
- ret = new BooleanValue(this.expr1.evaluate(ctx).booleanValue() &&
1475
- this.expr2.evaluate(ctx).booleanValue());
1476
- break;
1477
-
1478
- case '+':
1479
- ret = new NumberValue(this.expr1.evaluate(ctx).numberValue() +
1480
- this.expr2.evaluate(ctx).numberValue());
1481
- break;
1482
-
1483
- case '-':
1484
- ret = new NumberValue(this.expr1.evaluate(ctx).numberValue() -
1485
- this.expr2.evaluate(ctx).numberValue());
1486
- break;
1487
-
1488
- case '*':
1489
- ret = new NumberValue(this.expr1.evaluate(ctx).numberValue() *
1490
- this.expr2.evaluate(ctx).numberValue());
1491
- break;
1492
-
1493
- case 'mod':
1494
- ret = new NumberValue(this.expr1.evaluate(ctx).numberValue() %
1495
- this.expr2.evaluate(ctx).numberValue());
1496
- break;
1497
-
1498
- case 'div':
1499
- ret = new NumberValue(this.expr1.evaluate(ctx).numberValue() /
1500
- this.expr2.evaluate(ctx).numberValue());
1501
- break;
1502
-
1503
- case '=':
1504
- ret = this.compare(ctx, function(x1, x2) { return x1 == x2; });
1505
- break;
1506
-
1507
- case '!=':
1508
- ret = this.compare(ctx, function(x1, x2) { return x1 != x2; });
1509
- break;
1510
-
1511
- case '<':
1512
- ret = this.compare(ctx, function(x1, x2) { return x1 < x2; });
1513
- break;
1514
-
1515
- case '<=':
1516
- ret = this.compare(ctx, function(x1, x2) { return x1 <= x2; });
1517
- break;
1518
-
1519
- case '>':
1520
- ret = this.compare(ctx, function(x1, x2) { return x1 > x2; });
1521
- break;
1522
-
1523
- case '>=':
1524
- ret = this.compare(ctx, function(x1, x2) { return x1 >= x2; });
1525
- break;
1526
-
1527
- default:
1528
- alert('BinaryExpr.evaluate: ' + this.op.value);
1529
- }
1530
- return ret;
1531
- };
1532
-
1533
- BinaryExpr.prototype.compare = function(ctx, cmp) {
1534
- var v1 = this.expr1.evaluate(ctx);
1535
- var v2 = this.expr2.evaluate(ctx);
1536
-
1537
- var ret;
1538
- if (v1.type == 'node-set' && v2.type == 'node-set') {
1539
- var n1 = v1.nodeSetValue();
1540
- var n2 = v2.nodeSetValue();
1541
- ret = false;
1542
- for (var i1 = 0; i1 < n1.length; ++i1) {
1543
- for (var i2 = 0; i2 < n2.length; ++i2) {
1544
- if (cmp(xmlValue(n1[i1]), xmlValue(n2[i2]))) {
1545
- ret = true;
1546
- // Break outer loop. Labels confuse the jscompiler and we
1547
- // don't use them.
1548
- i2 = n2.length;
1549
- i1 = n1.length;
1550
- }
1551
- }
1552
- }
1553
-
1554
- } else if (v1.type == 'node-set' || v2.type == 'node-set') {
1555
-
1556
- if (v1.type == 'number') {
1557
- var s = v1.numberValue();
1558
- var n = v2.nodeSetValue();
1559
-
1560
- ret = false;
1561
- for (var i = 0; i < n.length; ++i) {
1562
- var nn = xmlValue(n[i]) - 0;
1563
- if (cmp(s, nn)) {
1564
- ret = true;
1565
- break;
1566
- }
1567
- }
1568
-
1569
- } else if (v2.type == 'number') {
1570
- var n = v1.nodeSetValue();
1571
- var s = v2.numberValue();
1572
-
1573
- ret = false;
1574
- for (var i = 0; i < n.length; ++i) {
1575
- var nn = xmlValue(n[i]) - 0;
1576
- if (cmp(nn, s)) {
1577
- ret = true;
1578
- break;
1579
- }
1580
- }
1581
-
1582
- } else if (v1.type == 'string') {
1583
- var s = v1.stringValue();
1584
- var n = v2.nodeSetValue();
1585
-
1586
- ret = false;
1587
- for (var i = 0; i < n.length; ++i) {
1588
- var nn = xmlValue(n[i]);
1589
- if (cmp(s, nn)) {
1590
- ret = true;
1591
- break;
1592
- }
1593
- }
1594
-
1595
- } else if (v2.type == 'string') {
1596
- var n = v1.nodeSetValue();
1597
- var s = v2.stringValue();
1598
-
1599
- ret = false;
1600
- for (var i = 0; i < n.length; ++i) {
1601
- var nn = xmlValue(n[i]);
1602
- if (cmp(nn, s)) {
1603
- ret = true;
1604
- break;
1605
- }
1606
- }
1607
-
1608
- } else {
1609
- ret = cmp(v1.booleanValue(), v2.booleanValue());
1610
- }
1611
-
1612
- } else if (v1.type == 'boolean' || v2.type == 'boolean') {
1613
- ret = cmp(v1.booleanValue(), v2.booleanValue());
1614
-
1615
- } else if (v1.type == 'number' || v2.type == 'number') {
1616
- ret = cmp(v1.numberValue(), v2.numberValue());
1617
-
1618
- } else {
1619
- ret = cmp(v1.stringValue(), v2.stringValue());
1620
- }
1621
-
1622
- return new BooleanValue(ret);
1623
- }
1624
-
1625
- function LiteralExpr(value) {
1626
- this.value = value;
1627
- }
1628
-
1629
- LiteralExpr.prototype.evaluate = function(ctx) {
1630
- return new StringValue(this.value);
1631
- };
1632
-
1633
- function NumberExpr(value) {
1634
- this.value = value;
1635
- }
1636
-
1637
- NumberExpr.prototype.evaluate = function(ctx) {
1638
- return new NumberValue(this.value);
1639
- };
1640
-
1641
- function VariableExpr(name) {
1642
- this.name = name;
1643
- }
1644
-
1645
- VariableExpr.prototype.evaluate = function(ctx) {
1646
- return ctx.getVariable(this.name);
1647
- }
1648
-
1649
- // Factory functions for semantic values (i.e. Expressions) of the
1650
- // productions in the grammar. When a production is matched to reduce
1651
- // the current parse state stack, the function is called with the
1652
- // semantic values of the matched elements as arguments, and returns
1653
- // another semantic value. The semantic value is a node of the parse
1654
- // tree, an expression object with an evaluate() method that evaluates the
1655
- // expression in an actual context. These factory functions are used
1656
- // in the specification of the grammar rules, below.
1657
-
1658
- function makeTokenExpr(m) {
1659
- return new TokenExpr(m);
1660
- }
1661
-
1662
- function passExpr(e) {
1663
- return e;
1664
- }
1665
-
1666
- function makeLocationExpr1(slash, rel) {
1667
- rel.absolute = true;
1668
- return rel;
1669
- }
1670
-
1671
- function makeLocationExpr2(dslash, rel) {
1672
- rel.absolute = true;
1673
- rel.prependStep(makeAbbrevStep(dslash.value));
1674
- return rel;
1675
- }
1676
-
1677
- function makeLocationExpr3(slash) {
1678
- var ret = new LocationExpr();
1679
- ret.appendStep(makeAbbrevStep('.'));
1680
- ret.absolute = true;
1681
- return ret;
1682
- }
1683
-
1684
- function makeLocationExpr4(dslash) {
1685
- var ret = new LocationExpr();
1686
- ret.absolute = true;
1687
- ret.appendStep(makeAbbrevStep(dslash.value));
1688
- return ret;
1689
- }
1690
-
1691
- function makeLocationExpr5(step) {
1692
- var ret = new LocationExpr();
1693
- ret.appendStep(step);
1694
- return ret;
1695
- }
1696
-
1697
- function makeLocationExpr6(rel, slash, step) {
1698
- rel.appendStep(step);
1699
- return rel;
1700
- }
1701
-
1702
- function makeLocationExpr7(rel, dslash, step) {
1703
- rel.appendStep(makeAbbrevStep(dslash.value));
1704
- rel.appendStep(step);
1705
- return rel;
1706
- }
1707
-
1708
- function makeStepExpr1(dot) {
1709
- return makeAbbrevStep(dot.value);
1710
- }
1711
-
1712
- function makeStepExpr2(ddot) {
1713
- return makeAbbrevStep(ddot.value);
1714
- }
1715
-
1716
- function makeStepExpr3(axisname, axis, nodetest) {
1717
- return new StepExpr(axisname.value, nodetest);
1718
- }
1719
-
1720
- function makeStepExpr4(at, nodetest) {
1721
- return new StepExpr('attribute', nodetest);
1722
- }
1723
-
1724
- function makeStepExpr5(nodetest) {
1725
- return new StepExpr('child', nodetest);
1726
- }
1727
-
1728
- function makeStepExpr6(step, predicate) {
1729
- step.appendPredicate(predicate);
1730
- return step;
1731
- }
1732
-
1733
- function makeAbbrevStep(abbrev) {
1734
- switch (abbrev) {
1735
- case '//':
1736
- return new StepExpr('descendant-or-self', new NodeTestAny);
1737
-
1738
- case '.':
1739
- return new StepExpr('self', new NodeTestAny);
1740
-
1741
- case '..':
1742
- return new StepExpr('parent', new NodeTestAny);
1743
- }
1744
- }
1745
-
1746
- function makeNodeTestExpr1(asterisk) {
1747
- return new NodeTestElementOrAttribute;
1748
- }
1749
-
1750
- function makeNodeTestExpr2(ncname, colon, asterisk) {
1751
- return new NodeTestNC(ncname.value);
1752
- }
1753
-
1754
- function makeNodeTestExpr3(qname) {
1755
- return new NodeTestName(qname.value);
1756
- }
1757
-
1758
- function makeNodeTestExpr4(typeo, parenc) {
1759
- var type = typeo.value.replace(/\s*\($/, '');
1760
- switch(type) {
1761
- case 'node':
1762
- return new NodeTestAny;
1763
-
1764
- case 'text':
1765
- return new NodeTestText;
1766
-
1767
- case 'comment':
1768
- return new NodeTestComment;
1769
-
1770
- case 'processing-instruction':
1771
- return new NodeTestPI('');
1772
- }
1773
- }
1774
-
1775
- function makeNodeTestExpr5(typeo, target, parenc) {
1776
- var type = typeo.replace(/\s*\($/, '');
1777
- if (type != 'processing-instruction') {
1778
- throw type;
1779
- }
1780
- return new NodeTestPI(target.value);
1781
- }
1782
-
1783
- function makePredicateExpr(pareno, expr, parenc) {
1784
- return new PredicateExpr(expr);
1785
- }
1786
-
1787
- function makePrimaryExpr(pareno, expr, parenc) {
1788
- return expr;
1789
- }
1790
-
1791
- function makeFunctionCallExpr1(name, pareno, parenc) {
1792
- return new FunctionCallExpr(name);
1793
- }
1794
-
1795
- function makeFunctionCallExpr2(name, pareno, arg1, args, parenc) {
1796
- var ret = new FunctionCallExpr(name);
1797
- ret.appendArg(arg1);
1798
- for (var i = 0; i < args.length; ++i) {
1799
- ret.appendArg(args[i]);
1800
- }
1801
- return ret;
1802
- }
1803
-
1804
- function makeArgumentExpr(comma, expr) {
1805
- return expr;
1806
- }
1807
-
1808
- function makeUnionExpr(expr1, pipe, expr2) {
1809
- return new UnionExpr(expr1, expr2);
1810
- }
1811
-
1812
- function makePathExpr1(filter, slash, rel) {
1813
- return new PathExpr(filter, rel);
1814
- }
1815
-
1816
- function makePathExpr2(filter, dslash, rel) {
1817
- rel.prependStep(makeAbbrevStep(dslash.value));
1818
- return new PathExpr(filter, rel);
1819
- }
1820
-
1821
- function makeFilterExpr(expr, predicates) {
1822
- if (predicates.length > 0) {
1823
- return new FilterExpr(expr, predicates);
1824
- } else {
1825
- return expr;
1826
- }
1827
- }
1828
-
1829
- function makeUnaryMinusExpr(minus, expr) {
1830
- return new UnaryMinusExpr(expr);
1831
- }
1832
-
1833
- function makeBinaryExpr(expr1, op, expr2) {
1834
- return new BinaryExpr(expr1, op, expr2);
1835
- }
1836
-
1837
- function makeLiteralExpr(token) {
1838
- // remove quotes from the parsed value:
1839
- var value = token.value.substring(1, token.value.length - 1);
1840
- return new LiteralExpr(value);
1841
- }
1842
-
1843
- function makeNumberExpr(token) {
1844
- return new NumberExpr(token.value);
1845
- }
1846
-
1847
- function makeVariableReference(dollar, name) {
1848
- return new VariableExpr(name.value);
1849
- }
1850
-
1851
- // Used before parsing for optimization of common simple cases. See
1852
- // the begin of xpathParse() for which they are.
1853
- function makeSimpleExpr(expr) {
1854
- if (expr.charAt(0) == '$') {
1855
- return new VariableExpr(expr.substr(1));
1856
- } else if (expr.charAt(0) == '@') {
1857
- var a = new NodeTestName(expr.substr(1));
1858
- var b = new StepExpr('attribute', a);
1859
- var c = new LocationExpr();
1860
- c.appendStep(b);
1861
- return c;
1862
- } else if (expr.match(/^[0-9]+$/)) {
1863
- return new NumberExpr(expr);
1864
- } else {
1865
- var a = new NodeTestName(expr);
1866
- var b = new StepExpr('child', a);
1867
- var c = new LocationExpr();
1868
- c.appendStep(b);
1869
- return c;
1870
- }
1871
- }
1872
-
1873
- function makeSimpleExpr2(expr) {
1874
- var steps = stringSplit(expr, '/');
1875
- var c = new LocationExpr();
1876
- for (var i = 0; i < steps.length; ++i) {
1877
- var a = new NodeTestName(steps[i]);
1878
- var b = new StepExpr('child', a);
1879
- c.appendStep(b);
1880
- }
1881
- return c;
1882
- }
1883
-
1884
- // The axes of XPath expressions.
1885
-
1886
- var xpathAxis = {
1887
- ANCESTOR_OR_SELF: 'ancestor-or-self',
1888
- ANCESTOR: 'ancestor',
1889
- ATTRIBUTE: 'attribute',
1890
- CHILD: 'child',
1891
- DESCENDANT_OR_SELF: 'descendant-or-self',
1892
- DESCENDANT: 'descendant',
1893
- FOLLOWING_SIBLING: 'following-sibling',
1894
- FOLLOWING: 'following',
1895
- NAMESPACE: 'namespace',
1896
- PARENT: 'parent',
1897
- PRECEDING_SIBLING: 'preceding-sibling',
1898
- PRECEDING: 'preceding',
1899
- SELF: 'self'
1900
- };
1901
-
1902
- var xpathAxesRe = [
1903
- xpathAxis.ANCESTOR_OR_SELF,
1904
- xpathAxis.ANCESTOR,
1905
- xpathAxis.ATTRIBUTE,
1906
- xpathAxis.CHILD,
1907
- xpathAxis.DESCENDANT_OR_SELF,
1908
- xpathAxis.DESCENDANT,
1909
- xpathAxis.FOLLOWING_SIBLING,
1910
- xpathAxis.FOLLOWING,
1911
- xpathAxis.NAMESPACE,
1912
- xpathAxis.PARENT,
1913
- xpathAxis.PRECEDING_SIBLING,
1914
- xpathAxis.PRECEDING,
1915
- xpathAxis.SELF
1916
- ].join('|');
1917
-
1918
-
1919
- // The tokens of the language. The label property is just used for
1920
- // generating debug output. The prec property is the precedence used
1921
- // for shift/reduce resolution. Default precedence is 0 as a lookahead
1922
- // token and 2 on the stack. TODO(mesch): this is certainly not
1923
- // necessary and too complicated. Simplify this!
1924
-
1925
- // NOTE: tabular formatting is the big exception, but here it should
1926
- // be OK.
1927
-
1928
- var TOK_PIPE = { label: "|", prec: 17, re: new RegExp("^\\|") };
1929
- var TOK_DSLASH = { label: "//", prec: 19, re: new RegExp("^//") };
1930
- var TOK_SLASH = { label: "/", prec: 30, re: new RegExp("^/") };
1931
- var TOK_AXIS = { label: "::", prec: 20, re: new RegExp("^::") };
1932
- var TOK_COLON = { label: ":", prec: 1000, re: new RegExp("^:") };
1933
- var TOK_AXISNAME = { label: "[axis]", re: new RegExp('^(' + xpathAxesRe + ')') };
1934
- var TOK_PARENO = { label: "(", prec: 34, re: new RegExp("^\\(") };
1935
- var TOK_PARENC = { label: ")", re: new RegExp("^\\)") };
1936
- var TOK_DDOT = { label: "..", prec: 34, re: new RegExp("^\\.\\.") };
1937
- var TOK_DOT = { label: ".", prec: 34, re: new RegExp("^\\.") };
1938
- var TOK_AT = { label: "@", prec: 34, re: new RegExp("^@") };
1939
-
1940
- var TOK_COMMA = { label: ",", re: new RegExp("^,") };
1941
-
1942
- var TOK_OR = { label: "or", prec: 10, re: new RegExp("^or\\b") };
1943
- var TOK_AND = { label: "and", prec: 11, re: new RegExp("^and\\b") };
1944
- var TOK_EQ = { label: "=", prec: 12, re: new RegExp("^=") };
1945
- var TOK_NEQ = { label: "!=", prec: 12, re: new RegExp("^!=") };
1946
- var TOK_GE = { label: ">=", prec: 13, re: new RegExp("^>=") };
1947
- var TOK_GT = { label: ">", prec: 13, re: new RegExp("^>") };
1948
- var TOK_LE = { label: "<=", prec: 13, re: new RegExp("^<=") };
1949
- var TOK_LT = { label: "<", prec: 13, re: new RegExp("^<") };
1950
- var TOK_PLUS = { label: "+", prec: 14, re: new RegExp("^\\+"), left: true };
1951
- var TOK_MINUS = { label: "-", prec: 14, re: new RegExp("^\\-"), left: true };
1952
- var TOK_DIV = { label: "div", prec: 15, re: new RegExp("^div\\b"), left: true };
1953
- var TOK_MOD = { label: "mod", prec: 15, re: new RegExp("^mod\\b"), left: true };
1954
-
1955
- var TOK_BRACKO = { label: "[", prec: 32, re: new RegExp("^\\[") };
1956
- var TOK_BRACKC = { label: "]", re: new RegExp("^\\]") };
1957
- var TOK_DOLLAR = { label: "$", re: new RegExp("^\\$") };
1958
-
1959
- var TOK_NCNAME = { label: "[ncname]", re: new RegExp('^' + XML_NC_NAME) };
1960
-
1961
- var TOK_ASTERISK = { label: "*", prec: 15, re: new RegExp("^\\*"), left: true };
1962
- var TOK_LITERALQ = { label: "[litq]", prec: 20, re: new RegExp("^'[^\\']*'") };
1963
- var TOK_LITERALQQ = {
1964
- label: "[litqq]",
1965
- prec: 20,
1966
- re: new RegExp('^"[^\\"]*"')
1967
- };
1968
-
1969
- var TOK_NUMBER = {
1970
- label: "[number]",
1971
- prec: 35,
1972
- re: new RegExp('^\\d+(\\.\\d*)?') };
1973
-
1974
- var TOK_QNAME = {
1975
- label: "[qname]",
1976
- re: new RegExp('^(' + XML_NC_NAME + ':)?' + XML_NC_NAME)
1977
- };
1978
-
1979
- var TOK_NODEO = {
1980
- label: "[nodetest-start]",
1981
- re: new RegExp('^(processing-instruction|comment|text|node)\\(')
1982
- };
1983
-
1984
- // The table of the tokens of our grammar, used by the lexer: first
1985
- // column the tag, second column a regexp to recognize it in the
1986
- // input, third column the precedence of the token, fourth column a
1987
- // factory function for the semantic value of the token.
1988
- //
1989
- // NOTE: order of this list is important, because the first match
1990
- // counts. Cf. DDOT and DOT, and AXIS and COLON.
1991
-
1992
- var xpathTokenRules = [
1993
- TOK_DSLASH,
1994
- TOK_SLASH,
1995
- TOK_DDOT,
1996
- TOK_DOT,
1997
- TOK_AXIS,
1998
- TOK_COLON,
1999
- TOK_AXISNAME,
2000
- TOK_NODEO,
2001
- TOK_PARENO,
2002
- TOK_PARENC,
2003
- TOK_BRACKO,
2004
- TOK_BRACKC,
2005
- TOK_AT,
2006
- TOK_COMMA,
2007
- TOK_OR,
2008
- TOK_AND,
2009
- TOK_NEQ,
2010
- TOK_EQ,
2011
- TOK_GE,
2012
- TOK_GT,
2013
- TOK_LE,
2014
- TOK_LT,
2015
- TOK_PLUS,
2016
- TOK_MINUS,
2017
- TOK_ASTERISK,
2018
- TOK_PIPE,
2019
- TOK_MOD,
2020
- TOK_DIV,
2021
- TOK_LITERALQ,
2022
- TOK_LITERALQQ,
2023
- TOK_NUMBER,
2024
- TOK_QNAME,
2025
- TOK_NCNAME,
2026
- TOK_DOLLAR
2027
- ];
2028
-
2029
- // All the nonterminals of the grammar. The nonterminal objects are
2030
- // identified by object identity; the labels are used in the debug
2031
- // output only.
2032
- var XPathLocationPath = { label: "LocationPath" };
2033
- var XPathRelativeLocationPath = { label: "RelativeLocationPath" };
2034
- var XPathAbsoluteLocationPath = { label: "AbsoluteLocationPath" };
2035
- var XPathStep = { label: "Step" };
2036
- var XPathNodeTest = { label: "NodeTest" };
2037
- var XPathPredicate = { label: "Predicate" };
2038
- var XPathLiteral = { label: "Literal" };
2039
- var XPathExpr = { label: "Expr" };
2040
- var XPathPrimaryExpr = { label: "PrimaryExpr" };
2041
- var XPathVariableReference = { label: "Variablereference" };
2042
- var XPathNumber = { label: "Number" };
2043
- var XPathFunctionCall = { label: "FunctionCall" };
2044
- var XPathArgumentRemainder = { label: "ArgumentRemainder" };
2045
- var XPathPathExpr = { label: "PathExpr" };
2046
- var XPathUnionExpr = { label: "UnionExpr" };
2047
- var XPathFilterExpr = { label: "FilterExpr" };
2048
- var XPathDigits = { label: "Digits" };
2049
-
2050
- var xpathNonTerminals = [
2051
- XPathLocationPath,
2052
- XPathRelativeLocationPath,
2053
- XPathAbsoluteLocationPath,
2054
- XPathStep,
2055
- XPathNodeTest,
2056
- XPathPredicate,
2057
- XPathLiteral,
2058
- XPathExpr,
2059
- XPathPrimaryExpr,
2060
- XPathVariableReference,
2061
- XPathNumber,
2062
- XPathFunctionCall,
2063
- XPathArgumentRemainder,
2064
- XPathPathExpr,
2065
- XPathUnionExpr,
2066
- XPathFilterExpr,
2067
- XPathDigits
2068
- ];
2069
-
2070
- // Quantifiers that are used in the productions of the grammar.
2071
- var Q_01 = { label: "?" };
2072
- var Q_MM = { label: "*" };
2073
- var Q_1M = { label: "+" };
2074
-
2075
- // Tag for left associativity (right assoc is implied by undefined).
2076
- var ASSOC_LEFT = true;
2077
-
2078
- // The productions of the grammar. Columns of the table:
2079
- //
2080
- // - target nonterminal,
2081
- // - pattern,
2082
- // - precedence,
2083
- // - semantic value factory
2084
- //
2085
- // The semantic value factory is a function that receives parse tree
2086
- // nodes from the stack frames of the matched symbols as arguments and
2087
- // returns an a node of the parse tree. The node is stored in the top
2088
- // stack frame along with the target object of the rule. The node in
2089
- // the parse tree is an expression object that has an evaluate() method
2090
- // and thus evaluates XPath expressions.
2091
- //
2092
- // The precedence is used to decide between reducing and shifting by
2093
- // comparing the precendence of the rule that is candidate for
2094
- // reducing with the precedence of the look ahead token. Precedence of
2095
- // -1 means that the precedence of the tokens in the pattern is used
2096
- // instead. TODO: It shouldn't be necessary to explicitly assign
2097
- // precedences to rules.
2098
-
2099
- // DGF As it stands, these precedences are purely empirical; we're
2100
- // not sure they can be made to be consistent at all.
2101
-
2102
- var xpathGrammarRules =
2103
- [
2104
- [ XPathLocationPath, [ XPathRelativeLocationPath ], 18,
2105
- passExpr ],
2106
- [ XPathLocationPath, [ XPathAbsoluteLocationPath ], 18,
2107
- passExpr ],
2108
-
2109
- [ XPathAbsoluteLocationPath, [ TOK_SLASH, XPathRelativeLocationPath ], 18,
2110
- makeLocationExpr1 ],
2111
- [ XPathAbsoluteLocationPath, [ TOK_DSLASH, XPathRelativeLocationPath ], 18,
2112
- makeLocationExpr2 ],
2113
-
2114
- [ XPathAbsoluteLocationPath, [ TOK_SLASH ], 0,
2115
- makeLocationExpr3 ],
2116
- [ XPathAbsoluteLocationPath, [ TOK_DSLASH ], 0,
2117
- makeLocationExpr4 ],
2118
-
2119
- [ XPathRelativeLocationPath, [ XPathStep ], 31,
2120
- makeLocationExpr5 ],
2121
- [ XPathRelativeLocationPath,
2122
- [ XPathRelativeLocationPath, TOK_SLASH, XPathStep ], 31,
2123
- makeLocationExpr6 ],
2124
- [ XPathRelativeLocationPath,
2125
- [ XPathRelativeLocationPath, TOK_DSLASH, XPathStep ], 31,
2126
- makeLocationExpr7 ],
2127
-
2128
- [ XPathStep, [ TOK_DOT ], 33,
2129
- makeStepExpr1 ],
2130
- [ XPathStep, [ TOK_DDOT ], 33,
2131
- makeStepExpr2 ],
2132
- [ XPathStep,
2133
- [ TOK_AXISNAME, TOK_AXIS, XPathNodeTest ], 33,
2134
- makeStepExpr3 ],
2135
- [ XPathStep, [ TOK_AT, XPathNodeTest ], 33,
2136
- makeStepExpr4 ],
2137
- [ XPathStep, [ XPathNodeTest ], 33,
2138
- makeStepExpr5 ],
2139
- [ XPathStep, [ XPathStep, XPathPredicate ], 33,
2140
- makeStepExpr6 ],
2141
-
2142
- [ XPathNodeTest, [ TOK_ASTERISK ], 33,
2143
- makeNodeTestExpr1 ],
2144
- [ XPathNodeTest, [ TOK_NCNAME, TOK_COLON, TOK_ASTERISK ], 33,
2145
- makeNodeTestExpr2 ],
2146
- [ XPathNodeTest, [ TOK_QNAME ], 33,
2147
- makeNodeTestExpr3 ],
2148
- [ XPathNodeTest, [ TOK_NODEO, TOK_PARENC ], 33,
2149
- makeNodeTestExpr4 ],
2150
- [ XPathNodeTest, [ TOK_NODEO, XPathLiteral, TOK_PARENC ], 33,
2151
- makeNodeTestExpr5 ],
2152
-
2153
- [ XPathPredicate, [ TOK_BRACKO, XPathExpr, TOK_BRACKC ], 33,
2154
- makePredicateExpr ],
2155
-
2156
- [ XPathPrimaryExpr, [ XPathVariableReference ], 33,
2157
- passExpr ],
2158
- [ XPathPrimaryExpr, [ TOK_PARENO, XPathExpr, TOK_PARENC ], 33,
2159
- makePrimaryExpr ],
2160
- [ XPathPrimaryExpr, [ XPathLiteral ], 30,
2161
- passExpr ],
2162
- [ XPathPrimaryExpr, [ XPathNumber ], 30,
2163
- passExpr ],
2164
- [ XPathPrimaryExpr, [ XPathFunctionCall ], 31,
2165
- passExpr ],
2166
-
2167
- [ XPathFunctionCall, [ TOK_QNAME, TOK_PARENO, TOK_PARENC ], -1,
2168
- makeFunctionCallExpr1 ],
2169
- [ XPathFunctionCall,
2170
- [ TOK_QNAME, TOK_PARENO, XPathExpr, XPathArgumentRemainder, Q_MM,
2171
- TOK_PARENC ], -1,
2172
- makeFunctionCallExpr2 ],
2173
- [ XPathArgumentRemainder, [ TOK_COMMA, XPathExpr ], -1,
2174
- makeArgumentExpr ],
2175
-
2176
- [ XPathUnionExpr, [ XPathPathExpr ], 20,
2177
- passExpr ],
2178
- [ XPathUnionExpr, [ XPathUnionExpr, TOK_PIPE, XPathPathExpr ], 20,
2179
- makeUnionExpr ],
2180
-
2181
- [ XPathPathExpr, [ XPathLocationPath ], 20,
2182
- passExpr ],
2183
- [ XPathPathExpr, [ XPathFilterExpr ], 19,
2184
- passExpr ],
2185
- [ XPathPathExpr,
2186
- [ XPathFilterExpr, TOK_SLASH, XPathRelativeLocationPath ], 19,
2187
- makePathExpr1 ],
2188
- [ XPathPathExpr,
2189
- [ XPathFilterExpr, TOK_DSLASH, XPathRelativeLocationPath ], 19,
2190
- makePathExpr2 ],
2191
-
2192
- [ XPathFilterExpr, [ XPathPrimaryExpr, XPathPredicate, Q_MM ], 31,
2193
- makeFilterExpr ],
2194
-
2195
- [ XPathExpr, [ XPathPrimaryExpr ], 16,
2196
- passExpr ],
2197
- [ XPathExpr, [ XPathUnionExpr ], 16,
2198
- passExpr ],
2199
-
2200
- [ XPathExpr, [ TOK_MINUS, XPathExpr ], -1,
2201
- makeUnaryMinusExpr ],
2202
-
2203
- [ XPathExpr, [ XPathExpr, TOK_OR, XPathExpr ], -1,
2204
- makeBinaryExpr ],
2205
- [ XPathExpr, [ XPathExpr, TOK_AND, XPathExpr ], -1,
2206
- makeBinaryExpr ],
2207
-
2208
- [ XPathExpr, [ XPathExpr, TOK_EQ, XPathExpr ], -1,
2209
- makeBinaryExpr ],
2210
- [ XPathExpr, [ XPathExpr, TOK_NEQ, XPathExpr ], -1,
2211
- makeBinaryExpr ],
2212
-
2213
- [ XPathExpr, [ XPathExpr, TOK_LT, XPathExpr ], -1,
2214
- makeBinaryExpr ],
2215
- [ XPathExpr, [ XPathExpr, TOK_LE, XPathExpr ], -1,
2216
- makeBinaryExpr ],
2217
- [ XPathExpr, [ XPathExpr, TOK_GT, XPathExpr ], -1,
2218
- makeBinaryExpr ],
2219
- [ XPathExpr, [ XPathExpr, TOK_GE, XPathExpr ], -1,
2220
- makeBinaryExpr ],
2221
-
2222
- [ XPathExpr, [ XPathExpr, TOK_PLUS, XPathExpr ], -1,
2223
- makeBinaryExpr, ASSOC_LEFT ],
2224
- [ XPathExpr, [ XPathExpr, TOK_MINUS, XPathExpr ], -1,
2225
- makeBinaryExpr, ASSOC_LEFT ],
2226
-
2227
- [ XPathExpr, [ XPathExpr, TOK_ASTERISK, XPathExpr ], -1,
2228
- makeBinaryExpr, ASSOC_LEFT ],
2229
- [ XPathExpr, [ XPathExpr, TOK_DIV, XPathExpr ], -1,
2230
- makeBinaryExpr, ASSOC_LEFT ],
2231
- [ XPathExpr, [ XPathExpr, TOK_MOD, XPathExpr ], -1,
2232
- makeBinaryExpr, ASSOC_LEFT ],
2233
-
2234
- [ XPathLiteral, [ TOK_LITERALQ ], -1,
2235
- makeLiteralExpr ],
2236
- [ XPathLiteral, [ TOK_LITERALQQ ], -1,
2237
- makeLiteralExpr ],
2238
-
2239
- [ XPathNumber, [ TOK_NUMBER ], -1,
2240
- makeNumberExpr ],
2241
-
2242
- [ XPathVariableReference, [ TOK_DOLLAR, TOK_QNAME ], 200,
2243
- makeVariableReference ]
2244
- ];
2245
-
2246
- // That function computes some optimizations of the above data
2247
- // structures and will be called right here. It merely takes the
2248
- // counter variables out of the global scope.
2249
-
2250
- var xpathRules = [];
2251
-
2252
- function xpathParseInit() {
2253
- if (xpathRules.length) {
2254
- return;
2255
- }
2256
-
2257
- // Some simple optimizations for the xpath expression parser: sort
2258
- // grammar rules descending by length, so that the longest match is
2259
- // first found.
2260
-
2261
- xpathGrammarRules.sort(function(a,b) {
2262
- var la = a[1].length;
2263
- var lb = b[1].length;
2264
- if (la < lb) {
2265
- return 1;
2266
- } else if (la > lb) {
2267
- return -1;
2268
- } else {
2269
- return 0;
2270
- }
2271
- });
2272
-
2273
- var k = 1;
2274
- for (var i = 0; i < xpathNonTerminals.length; ++i) {
2275
- xpathNonTerminals[i].key = k++;
2276
- }
2277
-
2278
- for (i = 0; i < xpathTokenRules.length; ++i) {
2279
- xpathTokenRules[i].key = k++;
2280
- }
2281
-
2282
- xpathLog('XPath parse INIT: ' + k + ' rules');
2283
-
2284
- // Another slight optimization: sort the rules into bins according
2285
- // to the last element (observing quantifiers), so we can restrict
2286
- // the match against the stack to the subest of rules that match the
2287
- // top of the stack.
2288
- //
2289
- // TODO(mesch): What we actually want is to compute states as in
2290
- // bison, so that we don't have to do any explicit and iterated
2291
- // match against the stack.
2292
-
2293
- function push_(array, position, element) {
2294
- if (!array[position]) {
2295
- array[position] = [];
2296
- }
2297
- array[position].push(element);
2298
- }
2299
-
2300
- for (i = 0; i < xpathGrammarRules.length; ++i) {
2301
- var rule = xpathGrammarRules[i];
2302
- var pattern = rule[1];
2303
-
2304
- for (var j = pattern.length - 1; j >= 0; --j) {
2305
- if (pattern[j] == Q_1M) {
2306
- push_(xpathRules, pattern[j-1].key, rule);
2307
- break;
2308
-
2309
- } else if (pattern[j] == Q_MM || pattern[j] == Q_01) {
2310
- push_(xpathRules, pattern[j-1].key, rule);
2311
- --j;
2312
-
2313
- } else {
2314
- push_(xpathRules, pattern[j].key, rule);
2315
- break;
2316
- }
2317
- }
2318
- }
2319
-
2320
- xpathLog('XPath parse INIT: ' + xpathRules.length + ' rule bins');
2321
-
2322
- var sum = 0;
2323
- mapExec(xpathRules, function(i) {
2324
- if (i) {
2325
- sum += i.length;
2326
- }
2327
- });
2328
-
2329
- xpathLog('XPath parse INIT: ' + (sum / xpathRules.length) +
2330
- ' average bin size');
2331
- }
2332
-
2333
- // Local utility functions that are used by the lexer or parser.
2334
-
2335
- function xpathCollectDescendants(nodelist, node, opt_tagName) {
2336
- if (opt_tagName && node.getElementsByTagName) {
2337
- copyArray(nodelist, node.getElementsByTagName(opt_tagName));
2338
- return;
2339
- }
2340
- for (var n = node.firstChild; n; n = n.nextSibling) {
2341
- nodelist.push(n);
2342
- xpathCollectDescendants(nodelist, n);
2343
- }
2344
- }
2345
-
2346
- // DGF extract a tag name suitable for getElementsByTagName
2347
- function xpathExtractTagNameFromNodeTest(nodetest) {
2348
- if (nodetest instanceof NodeTestName) {
2349
- return nodetest.name;
2350
- } else if (/* nodetest instanceof NodeTestAny || */ nodetest instanceof NodeTestElementOrAttribute) {
2351
- // HBC - commented out the NodeTestAny in the above condition; it causes
2352
- // non-element nodes to be excluded! The XPath spec says "node()" must
2353
- // match all node types.
2354
- return "*";
2355
- }
2356
- }
2357
-
2358
- function xpathCollectDescendantsReverse(nodelist, node) {
2359
- for (var n = node.lastChild; n; n = n.previousSibling) {
2360
- nodelist.push(n);
2361
- xpathCollectDescendantsReverse(nodelist, n);
2362
- }
2363
- }
2364
-
2365
-
2366
- // The entry point for the library: match an expression against a DOM
2367
- // node. Returns an XPath value.
2368
- function xpathDomEval(expr, node) {
2369
- var expr1 = xpathParse(expr);
2370
- var ret = expr1.evaluate(new ExprContext(node));
2371
- return ret;
2372
- }
2373
-
2374
- // Utility function to sort a list of nodes. Used by xsltSort() and
2375
- // nxslSelect().
2376
- function xpathSort(input, sort) {
2377
- if (sort.length == 0) {
2378
- return;
2379
- }
2380
-
2381
- var sortlist = [];
2382
-
2383
- for (var i = 0; i < input.contextSize(); ++i) {
2384
- var node = input.nodelist[i];
2385
- var sortitem = { node: node, key: [] };
2386
- var context = input.clone(node, 0, [ node ]);
2387
-
2388
- for (var j = 0; j < sort.length; ++j) {
2389
- var s = sort[j];
2390
- var value = s.expr.evaluate(context);
2391
-
2392
- var evalue;
2393
- if (s.type == 'text') {
2394
- evalue = value.stringValue();
2395
- } else if (s.type == 'number') {
2396
- evalue = value.numberValue();
2397
- }
2398
- sortitem.key.push({ value: evalue, order: s.order });
2399
- }
2400
-
2401
- // Make the sort stable by adding a lowest priority sort by
2402
- // id. This is very convenient and furthermore required by the
2403
- // spec ([XSLT] - Section 10 Sorting).
2404
- sortitem.key.push({ value: i, order: 'ascending' });
2405
-
2406
- sortlist.push(sortitem);
2407
- }
2408
-
2409
- sortlist.sort(xpathSortByKey);
2410
-
2411
- var nodes = [];
2412
- for (var i = 0; i < sortlist.length; ++i) {
2413
- nodes.push(sortlist[i].node);
2414
- }
2415
- input.nodelist = nodes;
2416
- input.setNode(0);
2417
- }
2418
-
2419
-
2420
- // Sorts by all order criteria defined. According to the JavaScript
2421
- // spec ([ECMA] Section 11.8.5), the compare operators compare strings
2422
- // as strings and numbers as numbers.
2423
- //
2424
- // NOTE: In browsers which do not follow the spec, this breaks only in
2425
- // the case that numbers should be sorted as strings, which is very
2426
- // uncommon.
2427
- function xpathSortByKey(v1, v2) {
2428
- // NOTE: Sort key vectors of different length never occur in
2429
- // xsltSort.
2430
-
2431
- for (var i = 0; i < v1.key.length; ++i) {
2432
- var o = v1.key[i].order == 'descending' ? -1 : 1;
2433
- if (v1.key[i].value > v2.key[i].value) {
2434
- return +1 * o;
2435
- } else if (v1.key[i].value < v2.key[i].value) {
2436
- return -1 * o;
2437
- }
2438
- }
2439
-
2440
- return 0;
2441
- }
2442
-
2443
-
2444
- // Parses and then evaluates the given XPath expression in the given
2445
- // input context. Notice that parsed xpath expressions are cached.
2446
- function xpathEval(select, context) {
2447
- var expr = xpathParse(select);
2448
- var ret = expr.evaluate(context);
2449
- return ret;
2450
- }