zena 1.2.7 → 1.2.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
- }