poly-cms 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (460) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +10 -0
  3. data/Gemfile +27 -0
  4. data/Gemfile.lock +95 -0
  5. data/README.md +3 -0
  6. data/Rakefile +45 -0
  7. data/bin/poly +88 -0
  8. data/config.ru +3 -0
  9. data/core/admin/assets/images/icons/cache-clear.svg +11 -0
  10. data/core/admin/assets/images/icons/delete-dark.svg +10 -0
  11. data/core/admin/assets/images/icons/delete.svg +10 -0
  12. data/core/admin/assets/images/icons/handle.svg +12 -0
  13. data/core/admin/assets/images/icons/logout.svg +13 -0
  14. data/core/admin/assets/images/icons/move.svg +10 -0
  15. data/core/admin/assets/images/icons/new.svg +9 -0
  16. data/core/admin/assets/images/icons/prompt.svg +11 -0
  17. data/core/admin/assets/images/icons/refresh.svg +40 -0
  18. data/core/admin/assets/images/icons/save.svg +7 -0
  19. data/core/admin/assets/images/poly-small-boxed.svg +51 -0
  20. data/core/admin/assets/images/poly-small.svg +52 -0
  21. data/core/admin/assets/images/poly.svg +36 -0
  22. data/core/admin/assets/js/app/file-ext.js +15 -0
  23. data/core/admin/assets/js/app/views/editor.js +300 -0
  24. data/core/admin/assets/js/app/views/git.js +65 -0
  25. data/core/admin/assets/js/app/views/main.js +59 -0
  26. data/core/admin/assets/js/main.js +44 -0
  27. data/core/admin/assets/js/routes.js +25 -0
  28. data/core/admin/assets/js/vendor/backbone.js +4 -0
  29. data/core/admin/assets/js/vendor/codemirror/.gitattributes +8 -0
  30. data/core/admin/assets/js/vendor/codemirror/.gitignore +6 -0
  31. data/core/admin/assets/js/vendor/codemirror/.travis.yml +3 -0
  32. data/core/admin/assets/js/vendor/codemirror/addon/comment/comment.js +145 -0
  33. data/core/admin/assets/js/vendor/codemirror/addon/comment/continuecomment.js +54 -0
  34. data/core/admin/assets/js/vendor/codemirror/addon/dialog/dialog.css +32 -0
  35. data/core/admin/assets/js/vendor/codemirror/addon/dialog/dialog.js +80 -0
  36. data/core/admin/assets/js/vendor/codemirror/addon/display/fullscreen.css +6 -0
  37. data/core/admin/assets/js/vendor/codemirror/addon/display/fullscreen.js +30 -0
  38. data/core/admin/assets/js/vendor/codemirror/addon/display/placeholder.js +54 -0
  39. data/core/admin/assets/js/vendor/codemirror/addon/edit/closebrackets.js +82 -0
  40. data/core/admin/assets/js/vendor/codemirror/addon/edit/closetag.js +87 -0
  41. data/core/admin/assets/js/vendor/codemirror/addon/edit/continuelist.js +25 -0
  42. data/core/admin/assets/js/vendor/codemirror/addon/edit/matchbrackets.js +86 -0
  43. data/core/admin/assets/js/vendor/codemirror/addon/edit/matchtags.js +56 -0
  44. data/core/admin/assets/js/vendor/codemirror/addon/edit/trailingspace.js +15 -0
  45. data/core/admin/assets/js/vendor/codemirror/addon/fold/brace-fold.js +93 -0
  46. data/core/admin/assets/js/vendor/codemirror/addon/fold/comment-fold.js +40 -0
  47. data/core/admin/assets/js/vendor/codemirror/addon/fold/foldcode.js +75 -0
  48. data/core/admin/assets/js/vendor/codemirror/addon/fold/foldgutter.css +21 -0
  49. data/core/admin/assets/js/vendor/codemirror/addon/fold/foldgutter.js +124 -0
  50. data/core/admin/assets/js/vendor/codemirror/addon/fold/indent-fold.js +26 -0
  51. data/core/admin/assets/js/vendor/codemirror/addon/fold/xml-fold.js +167 -0
  52. data/core/admin/assets/js/vendor/codemirror/addon/hint/anyword-hint.js +34 -0
  53. data/core/admin/assets/js/vendor/codemirror/addon/hint/css-hint.js +50 -0
  54. data/core/admin/assets/js/vendor/codemirror/addon/hint/html-hint.js +337 -0
  55. data/core/admin/assets/js/vendor/codemirror/addon/hint/javascript-hint.js +130 -0
  56. data/core/admin/assets/js/vendor/codemirror/addon/hint/pig-hint.js +121 -0
  57. data/core/admin/assets/js/vendor/codemirror/addon/hint/python-hint.js +95 -0
  58. data/core/admin/assets/js/vendor/codemirror/addon/hint/show-hint.css +38 -0
  59. data/core/admin/assets/js/vendor/codemirror/addon/hint/show-hint.js +274 -0
  60. data/core/admin/assets/js/vendor/codemirror/addon/hint/sql-hint.js +105 -0
  61. data/core/admin/assets/js/vendor/codemirror/addon/hint/xml-hint.js +69 -0
  62. data/core/admin/assets/js/vendor/codemirror/addon/lint/coffeescript-lint.js +27 -0
  63. data/core/admin/assets/js/vendor/codemirror/addon/lint/css-lint.js +19 -0
  64. data/core/admin/assets/js/vendor/codemirror/addon/lint/javascript-lint.js +126 -0
  65. data/core/admin/assets/js/vendor/codemirror/addon/lint/json-lint.js +17 -0
  66. data/core/admin/assets/js/vendor/codemirror/addon/lint/lint.css +73 -0
  67. data/core/admin/assets/js/vendor/codemirror/addon/lint/lint.js +203 -0
  68. data/core/admin/assets/js/vendor/codemirror/addon/merge/dep/diff_match_patch.js +50 -0
  69. data/core/admin/assets/js/vendor/codemirror/addon/merge/merge.css +92 -0
  70. data/core/admin/assets/js/vendor/codemirror/addon/merge/merge.js +474 -0
  71. data/core/admin/assets/js/vendor/codemirror/addon/mode/loadmode.js +51 -0
  72. data/core/admin/assets/js/vendor/codemirror/addon/mode/multiplex.js +101 -0
  73. data/core/admin/assets/js/vendor/codemirror/addon/mode/multiplex_test.js +30 -0
  74. data/core/admin/assets/js/vendor/codemirror/addon/mode/overlay.js +59 -0
  75. data/core/admin/assets/js/vendor/codemirror/addon/runmode/colorize.js +29 -0
  76. data/core/admin/assets/js/vendor/codemirror/addon/runmode/runmode-standalone.js +136 -0
  77. data/core/admin/assets/js/vendor/codemirror/addon/runmode/runmode.js +56 -0
  78. data/core/admin/assets/js/vendor/codemirror/addon/runmode/runmode.node.js +103 -0
  79. data/core/admin/assets/js/vendor/codemirror/addon/scroll/scrollpastend.js +34 -0
  80. data/core/admin/assets/js/vendor/codemirror/addon/search/match-highlighter.js +91 -0
  81. data/core/admin/assets/js/vendor/codemirror/addon/search/search.js +133 -0
  82. data/core/admin/assets/js/vendor/codemirror/addon/search/searchcursor.js +143 -0
  83. data/core/admin/assets/js/vendor/codemirror/addon/selection/active-line.js +39 -0
  84. data/core/admin/assets/js/vendor/codemirror/addon/selection/mark-selection.js +108 -0
  85. data/core/admin/assets/js/vendor/codemirror/addon/tern/tern.css +85 -0
  86. data/core/admin/assets/js/vendor/codemirror/addon/tern/tern.js +632 -0
  87. data/core/admin/assets/js/vendor/codemirror/addon/tern/worker.js +41 -0
  88. data/core/admin/assets/js/vendor/codemirror/addon/wrap/hardwrap.js +99 -0
  89. data/core/admin/assets/js/vendor/codemirror/bin/authors.sh +6 -0
  90. data/core/admin/assets/js/vendor/codemirror/bin/compress +92 -0
  91. data/core/admin/assets/js/vendor/codemirror/bin/lint +16 -0
  92. data/core/admin/assets/js/vendor/codemirror/bin/source-highlight +61 -0
  93. data/core/admin/assets/js/vendor/codemirror/bower.json +15 -0
  94. data/core/admin/assets/js/vendor/codemirror/demo/activeline.html +78 -0
  95. data/core/admin/assets/js/vendor/codemirror/demo/anywordhint.html +79 -0
  96. data/core/admin/assets/js/vendor/codemirror/demo/bidi.html +74 -0
  97. data/core/admin/assets/js/vendor/codemirror/demo/btree.html +86 -0
  98. data/core/admin/assets/js/vendor/codemirror/demo/buffers.html +109 -0
  99. data/core/admin/assets/js/vendor/codemirror/demo/changemode.html +59 -0
  100. data/core/admin/assets/js/vendor/codemirror/demo/closebrackets.html +63 -0
  101. data/core/admin/assets/js/vendor/codemirror/demo/closetag.html +40 -0
  102. data/core/admin/assets/js/vendor/codemirror/demo/complete.html +80 -0
  103. data/core/admin/assets/js/vendor/codemirror/demo/emacs.html +75 -0
  104. data/core/admin/assets/js/vendor/codemirror/demo/folding.html +75 -0
  105. data/core/admin/assets/js/vendor/codemirror/demo/fullscreen.html +130 -0
  106. data/core/admin/assets/js/vendor/codemirror/demo/hardwrap.html +69 -0
  107. data/core/admin/assets/js/vendor/codemirror/demo/html5complete.html +54 -0
  108. data/core/admin/assets/js/vendor/codemirror/demo/indentwrap.html +58 -0
  109. data/core/admin/assets/js/vendor/codemirror/demo/lint.html +171 -0
  110. data/core/admin/assets/js/vendor/codemirror/demo/loadmode.html +49 -0
  111. data/core/admin/assets/js/vendor/codemirror/demo/marker.html +52 -0
  112. data/core/admin/assets/js/vendor/codemirror/demo/markselection.html +45 -0
  113. data/core/admin/assets/js/vendor/codemirror/demo/matchhighlighter.html +47 -0
  114. data/core/admin/assets/js/vendor/codemirror/demo/matchtags.html +49 -0
  115. data/core/admin/assets/js/vendor/codemirror/demo/merge.html +82 -0
  116. data/core/admin/assets/js/vendor/codemirror/demo/multiplex.html +75 -0
  117. data/core/admin/assets/js/vendor/codemirror/demo/mustache.html +68 -0
  118. data/core/admin/assets/js/vendor/codemirror/demo/placeholder.html +45 -0
  119. data/core/admin/assets/js/vendor/codemirror/demo/preview.html +88 -0
  120. data/core/admin/assets/js/vendor/codemirror/demo/resize.html +58 -0
  121. data/core/admin/assets/js/vendor/codemirror/demo/runmode.html +62 -0
  122. data/core/admin/assets/js/vendor/codemirror/demo/search.html +94 -0
  123. data/core/admin/assets/js/vendor/codemirror/demo/spanaffectswrapping_shim.html +85 -0
  124. data/core/admin/assets/js/vendor/codemirror/demo/tern.html +128 -0
  125. data/core/admin/assets/js/vendor/codemirror/demo/theme.html +121 -0
  126. data/core/admin/assets/js/vendor/codemirror/demo/trailingspace.html +48 -0
  127. data/core/admin/assets/js/vendor/codemirror/demo/variableheight.html +61 -0
  128. data/core/admin/assets/js/vendor/codemirror/demo/vim.html +74 -0
  129. data/core/admin/assets/js/vendor/codemirror/demo/visibletabs.html +62 -0
  130. data/core/admin/assets/js/vendor/codemirror/demo/widget.html +85 -0
  131. data/core/admin/assets/js/vendor/codemirror/demo/xmlcomplete.html +116 -0
  132. data/core/admin/assets/js/vendor/codemirror/doc/activebookmark.js +42 -0
  133. data/core/admin/assets/js/vendor/codemirror/doc/compress.html +231 -0
  134. data/core/admin/assets/js/vendor/codemirror/doc/docs.css +226 -0
  135. data/core/admin/assets/js/vendor/codemirror/doc/internals.html +503 -0
  136. data/core/admin/assets/js/vendor/codemirror/doc/logo.png +0 -0
  137. data/core/admin/assets/js/vendor/codemirror/doc/logo.svg +147 -0
  138. data/core/admin/assets/js/vendor/codemirror/doc/manual.html +2512 -0
  139. data/core/admin/assets/js/vendor/codemirror/doc/realworld.html +134 -0
  140. data/core/admin/assets/js/vendor/codemirror/doc/releases.html +779 -0
  141. data/core/admin/assets/js/vendor/codemirror/doc/reporting.html +61 -0
  142. data/core/admin/assets/js/vendor/codemirror/doc/upgrade_v2.2.html +96 -0
  143. data/core/admin/assets/js/vendor/codemirror/doc/upgrade_v3.html +230 -0
  144. data/core/admin/assets/js/vendor/codemirror/index.html +192 -0
  145. data/core/admin/assets/js/vendor/codemirror/keymap/emacs.js +387 -0
  146. data/core/admin/assets/js/vendor/codemirror/keymap/extra.js +43 -0
  147. data/core/admin/assets/js/vendor/codemirror/keymap/vim.js +3704 -0
  148. data/core/admin/assets/js/vendor/codemirror/lib/codemirror.css +263 -0
  149. data/core/admin/assets/js/vendor/codemirror/lib/codemirror.js +5910 -0
  150. data/core/admin/assets/js/vendor/codemirror/mode/apl/apl.js +160 -0
  151. data/core/admin/assets/js/vendor/codemirror/mode/apl/index.html +72 -0
  152. data/core/admin/assets/js/vendor/codemirror/mode/asterisk/asterisk.js +183 -0
  153. data/core/admin/assets/js/vendor/codemirror/mode/asterisk/index.html +154 -0
  154. data/core/admin/assets/js/vendor/codemirror/mode/clike/clike.js +362 -0
  155. data/core/admin/assets/js/vendor/codemirror/mode/clike/index.html +195 -0
  156. data/core/admin/assets/js/vendor/codemirror/mode/clike/scala.html +767 -0
  157. data/core/admin/assets/js/vendor/codemirror/mode/clojure/clojure.js +224 -0
  158. data/core/admin/assets/js/vendor/codemirror/mode/clojure/index.html +88 -0
  159. data/core/admin/assets/js/vendor/codemirror/mode/cobol/cobol.js +240 -0
  160. data/core/admin/assets/js/vendor/codemirror/mode/cobol/index.html +210 -0
  161. data/core/admin/assets/js/vendor/codemirror/mode/coffeescript/coffeescript.js +349 -0
  162. data/core/admin/assets/js/vendor/codemirror/mode/coffeescript/index.html +740 -0
  163. data/core/admin/assets/js/vendor/codemirror/mode/commonlisp/commonlisp.js +105 -0
  164. data/core/admin/assets/js/vendor/codemirror/mode/commonlisp/index.html +177 -0
  165. data/core/admin/assets/js/vendor/codemirror/mode/css/css.js +639 -0
  166. data/core/admin/assets/js/vendor/codemirror/mode/css/index.html +70 -0
  167. data/core/admin/assets/js/vendor/codemirror/mode/css/scss.html +157 -0
  168. data/core/admin/assets/js/vendor/codemirror/mode/css/scss_test.js +84 -0
  169. data/core/admin/assets/js/vendor/codemirror/mode/css/test.js +130 -0
  170. data/core/admin/assets/js/vendor/codemirror/mode/d/d.js +205 -0
  171. data/core/admin/assets/js/vendor/codemirror/mode/d/index.html +273 -0
  172. data/core/admin/assets/js/vendor/codemirror/mode/diff/diff.js +32 -0
  173. data/core/admin/assets/js/vendor/codemirror/mode/diff/index.html +117 -0
  174. data/core/admin/assets/js/vendor/codemirror/mode/dtd/dtd.js +127 -0
  175. data/core/admin/assets/js/vendor/codemirror/mode/dtd/index.html +89 -0
  176. data/core/admin/assets/js/vendor/codemirror/mode/ecl/ecl.js +192 -0
  177. data/core/admin/assets/js/vendor/codemirror/mode/ecl/index.html +52 -0
  178. data/core/admin/assets/js/vendor/codemirror/mode/eiffel/eiffel.js +147 -0
  179. data/core/admin/assets/js/vendor/codemirror/mode/eiffel/index.html +430 -0
  180. data/core/admin/assets/js/vendor/codemirror/mode/erlang/erlang.js +484 -0
  181. data/core/admin/assets/js/vendor/codemirror/mode/erlang/index.html +75 -0
  182. data/core/admin/assets/js/vendor/codemirror/mode/fortran/fortran.js +173 -0
  183. data/core/admin/assets/js/vendor/codemirror/mode/fortran/index.html +81 -0
  184. data/core/admin/assets/js/vendor/codemirror/mode/gas/gas.js +330 -0
  185. data/core/admin/assets/js/vendor/codemirror/mode/gas/index.html +68 -0
  186. data/core/admin/assets/js/vendor/codemirror/mode/gfm/gfm.js +97 -0
  187. data/core/admin/assets/js/vendor/codemirror/mode/gfm/index.html +82 -0
  188. data/core/admin/assets/js/vendor/codemirror/mode/gfm/test.js +112 -0
  189. data/core/admin/assets/js/vendor/codemirror/mode/gherkin/gherkin.js +168 -0
  190. data/core/admin/assets/js/vendor/codemirror/mode/gherkin/index.html +48 -0
  191. data/core/admin/assets/js/vendor/codemirror/mode/go/go.js +168 -0
  192. data/core/admin/assets/js/vendor/codemirror/mode/go/index.html +85 -0
  193. data/core/admin/assets/js/vendor/codemirror/mode/groovy/groovy.js +211 -0
  194. data/core/admin/assets/js/vendor/codemirror/mode/groovy/index.html +84 -0
  195. data/core/admin/assets/js/vendor/codemirror/mode/haml/haml.js +153 -0
  196. data/core/admin/assets/js/vendor/codemirror/mode/haml/index.html +79 -0
  197. data/core/admin/assets/js/vendor/codemirror/mode/haml/test.js +94 -0
  198. data/core/admin/assets/js/vendor/codemirror/mode/haskell/haskell.js +250 -0
  199. data/core/admin/assets/js/vendor/codemirror/mode/haskell/index.html +73 -0
  200. data/core/admin/assets/js/vendor/codemirror/mode/haxe/haxe.js +429 -0
  201. data/core/admin/assets/js/vendor/codemirror/mode/haxe/index.html +103 -0
  202. data/core/admin/assets/js/vendor/codemirror/mode/htmlembedded/htmlembedded.js +73 -0
  203. data/core/admin/assets/js/vendor/codemirror/mode/htmlembedded/index.html +60 -0
  204. data/core/admin/assets/js/vendor/codemirror/mode/htmlmixed/htmlmixed.js +104 -0
  205. data/core/admin/assets/js/vendor/codemirror/mode/htmlmixed/index.html +85 -0
  206. data/core/admin/assets/js/vendor/codemirror/mode/http/http.js +98 -0
  207. data/core/admin/assets/js/vendor/codemirror/mode/http/index.html +45 -0
  208. data/core/admin/assets/js/vendor/codemirror/mode/index.html +112 -0
  209. data/core/admin/assets/js/vendor/codemirror/mode/jade/index.html +66 -0
  210. data/core/admin/assets/js/vendor/codemirror/mode/jade/jade.js +90 -0
  211. data/core/admin/assets/js/vendor/codemirror/mode/javascript/index.html +107 -0
  212. data/core/admin/assets/js/vendor/codemirror/mode/javascript/javascript.js +480 -0
  213. data/core/admin/assets/js/vendor/codemirror/mode/javascript/test.js +10 -0
  214. data/core/admin/assets/js/vendor/codemirror/mode/javascript/typescript.html +61 -0
  215. data/core/admin/assets/js/vendor/codemirror/mode/jinja2/index.html +50 -0
  216. data/core/admin/assets/js/vendor/codemirror/mode/jinja2/jinja2.js +42 -0
  217. data/core/admin/assets/js/vendor/codemirror/mode/less/index.html +753 -0
  218. data/core/admin/assets/js/vendor/codemirror/mode/less/less.js +344 -0
  219. data/core/admin/assets/js/vendor/codemirror/mode/livescript/index.html +459 -0
  220. data/core/admin/assets/js/vendor/codemirror/mode/livescript/livescript.js +267 -0
  221. data/core/admin/assets/js/vendor/codemirror/mode/livescript/livescript.ls +266 -0
  222. data/core/admin/assets/js/vendor/codemirror/mode/lua/index.html +86 -0
  223. data/core/admin/assets/js/vendor/codemirror/mode/lua/lua.js +144 -0
  224. data/core/admin/assets/js/vendor/codemirror/mode/markdown/index.html +359 -0
  225. data/core/admin/assets/js/vendor/codemirror/mode/markdown/markdown.js +551 -0
  226. data/core/admin/assets/js/vendor/codemirror/mode/markdown/test.js +656 -0
  227. data/core/admin/assets/js/vendor/codemirror/mode/meta.js +89 -0
  228. data/core/admin/assets/js/vendor/codemirror/mode/mirc/index.html +161 -0
  229. data/core/admin/assets/js/vendor/codemirror/mode/mirc/mirc.js +177 -0
  230. data/core/admin/assets/js/vendor/codemirror/mode/nginx/index.html +181 -0
  231. data/core/admin/assets/js/vendor/codemirror/mode/nginx/nginx.js +163 -0
  232. data/core/admin/assets/js/vendor/codemirror/mode/ntriples/index.html +45 -0
  233. data/core/admin/assets/js/vendor/codemirror/mode/ntriples/ntriples.js +170 -0
  234. data/core/admin/assets/js/vendor/codemirror/mode/ocaml/index.html +146 -0
  235. data/core/admin/assets/js/vendor/codemirror/mode/ocaml/ocaml.js +116 -0
  236. data/core/admin/assets/js/vendor/codemirror/mode/octave/index.html +95 -0
  237. data/core/admin/assets/js/vendor/codemirror/mode/octave/octave.js +118 -0
  238. data/core/admin/assets/js/vendor/codemirror/mode/pascal/index.html +61 -0
  239. data/core/admin/assets/js/vendor/codemirror/mode/pascal/pascal.js +94 -0
  240. data/core/admin/assets/js/vendor/codemirror/mode/perl/index.html +75 -0
  241. data/core/admin/assets/js/vendor/codemirror/mode/perl/perl.js +816 -0
  242. data/core/admin/assets/js/vendor/codemirror/mode/php/index.html +62 -0
  243. data/core/admin/assets/js/vendor/codemirror/mode/php/php.js +132 -0
  244. data/core/admin/assets/js/vendor/codemirror/mode/pig/index.html +55 -0
  245. data/core/admin/assets/js/vendor/codemirror/mode/pig/pig.js +171 -0
  246. data/core/admin/assets/js/vendor/codemirror/mode/properties/index.html +53 -0
  247. data/core/admin/assets/js/vendor/codemirror/mode/properties/properties.js +63 -0
  248. data/core/admin/assets/js/vendor/codemirror/mode/python/index.html +187 -0
  249. data/core/admin/assets/js/vendor/codemirror/mode/python/python.js +368 -0
  250. data/core/admin/assets/js/vendor/codemirror/mode/q/index.html +144 -0
  251. data/core/admin/assets/js/vendor/codemirror/mode/q/q.js +124 -0
  252. data/core/admin/assets/js/vendor/codemirror/mode/r/index.html +86 -0
  253. data/core/admin/assets/js/vendor/codemirror/mode/r/r.js +141 -0
  254. data/core/admin/assets/js/vendor/codemirror/mode/rpm/changes/changes.js +19 -0
  255. data/core/admin/assets/js/vendor/codemirror/mode/rpm/changes/index.html +67 -0
  256. data/core/admin/assets/js/vendor/codemirror/mode/rpm/spec/index.html +114 -0
  257. data/core/admin/assets/js/vendor/codemirror/mode/rpm/spec/spec.css +5 -0
  258. data/core/admin/assets/js/vendor/codemirror/mode/rpm/spec/spec.js +66 -0
  259. data/core/admin/assets/js/vendor/codemirror/mode/rst/index.html +534 -0
  260. data/core/admin/assets/js/vendor/codemirror/mode/rst/rst.js +560 -0
  261. data/core/admin/assets/js/vendor/codemirror/mode/ruby/index.html +185 -0
  262. data/core/admin/assets/js/vendor/codemirror/mode/ruby/ruby.js +247 -0
  263. data/core/admin/assets/js/vendor/codemirror/mode/rust/index.html +61 -0
  264. data/core/admin/assets/js/vendor/codemirror/mode/rust/rust.js +436 -0
  265. data/core/admin/assets/js/vendor/codemirror/mode/sass/index.html +66 -0
  266. data/core/admin/assets/js/vendor/codemirror/mode/sass/sass.js +330 -0
  267. data/core/admin/assets/js/vendor/codemirror/mode/scheme/index.html +77 -0
  268. data/core/admin/assets/js/vendor/codemirror/mode/scheme/scheme.js +232 -0
  269. data/core/admin/assets/js/vendor/codemirror/mode/shell/index.html +66 -0
  270. data/core/admin/assets/js/vendor/codemirror/mode/shell/shell.js +118 -0
  271. data/core/admin/assets/js/vendor/codemirror/mode/sieve/index.html +93 -0
  272. data/core/admin/assets/js/vendor/codemirror/mode/sieve/sieve.js +183 -0
  273. data/core/admin/assets/js/vendor/codemirror/mode/smalltalk/index.html +68 -0
  274. data/core/admin/assets/js/vendor/codemirror/mode/smalltalk/smalltalk.js +151 -0
  275. data/core/admin/assets/js/vendor/codemirror/mode/smarty/index.html +136 -0
  276. data/core/admin/assets/js/vendor/codemirror/mode/smarty/smarty.js +205 -0
  277. data/core/admin/assets/js/vendor/codemirror/mode/smartymixed/index.html +114 -0
  278. data/core/admin/assets/js/vendor/codemirror/mode/smartymixed/smartymixed.js +175 -0
  279. data/core/admin/assets/js/vendor/codemirror/mode/sparql/index.html +54 -0
  280. data/core/admin/assets/js/vendor/codemirror/mode/sparql/sparql.js +145 -0
  281. data/core/admin/assets/js/vendor/codemirror/mode/sql/index.html +75 -0
  282. data/core/admin/assets/js/vendor/codemirror/mode/sql/sql.js +365 -0
  283. data/core/admin/assets/js/vendor/codemirror/mode/stex/index.html +110 -0
  284. data/core/admin/assets/js/vendor/codemirror/mode/stex/stex.js +246 -0
  285. data/core/admin/assets/js/vendor/codemirror/mode/stex/test.js +120 -0
  286. data/core/admin/assets/js/vendor/codemirror/mode/tcl/index.html +143 -0
  287. data/core/admin/assets/js/vendor/codemirror/mode/tcl/tcl.js +131 -0
  288. data/core/admin/assets/js/vendor/codemirror/mode/tiddlywiki/index.html +155 -0
  289. data/core/admin/assets/js/vendor/codemirror/mode/tiddlywiki/tiddlywiki.css +14 -0
  290. data/core/admin/assets/js/vendor/codemirror/mode/tiddlywiki/tiddlywiki.js +353 -0
  291. data/core/admin/assets/js/vendor/codemirror/mode/tiki/index.html +95 -0
  292. data/core/admin/assets/js/vendor/codemirror/mode/tiki/tiki.css +26 -0
  293. data/core/admin/assets/js/vendor/codemirror/mode/tiki/tiki.js +308 -0
  294. data/core/admin/assets/js/vendor/codemirror/mode/toml/index.html +73 -0
  295. data/core/admin/assets/js/vendor/codemirror/mode/toml/toml.js +71 -0
  296. data/core/admin/assets/js/vendor/codemirror/mode/turtle/index.html +51 -0
  297. data/core/admin/assets/js/vendor/codemirror/mode/turtle/turtle.js +145 -0
  298. data/core/admin/assets/js/vendor/codemirror/mode/vb/index.html +103 -0
  299. data/core/admin/assets/js/vendor/codemirror/mode/vb/vb.js +259 -0
  300. data/core/admin/assets/js/vendor/codemirror/mode/vbscript/index.html +55 -0
  301. data/core/admin/assets/js/vendor/codemirror/mode/vbscript/vbscript.js +334 -0
  302. data/core/admin/assets/js/vendor/codemirror/mode/velocity/index.html +119 -0
  303. data/core/admin/assets/js/vendor/codemirror/mode/velocity/velocity.js +186 -0
  304. data/core/admin/assets/js/vendor/codemirror/mode/verilog/index.html +132 -0
  305. data/core/admin/assets/js/vendor/codemirror/mode/verilog/verilog.js +182 -0
  306. data/core/admin/assets/js/vendor/codemirror/mode/xml/index.html +57 -0
  307. data/core/admin/assets/js/vendor/codemirror/mode/xml/xml.js +345 -0
  308. data/core/admin/assets/js/vendor/codemirror/mode/xquery/index.html +210 -0
  309. data/core/admin/assets/js/vendor/codemirror/mode/xquery/test.js +64 -0
  310. data/core/admin/assets/js/vendor/codemirror/mode/xquery/xquery.js +432 -0
  311. data/core/admin/assets/js/vendor/codemirror/mode/yaml/index.html +80 -0
  312. data/core/admin/assets/js/vendor/codemirror/mode/yaml/yaml.js +97 -0
  313. data/core/admin/assets/js/vendor/codemirror/mode/z80/index.html +52 -0
  314. data/core/admin/assets/js/vendor/codemirror/mode/z80/z80.js +85 -0
  315. data/core/admin/assets/js/vendor/codemirror/package.json +19 -0
  316. data/core/admin/assets/js/vendor/codemirror/test/comment_test.js +51 -0
  317. data/core/admin/assets/js/vendor/codemirror/test/doc_test.js +329 -0
  318. data/core/admin/assets/js/vendor/codemirror/test/driver.js +139 -0
  319. data/core/admin/assets/js/vendor/codemirror/test/emacs_test.js +135 -0
  320. data/core/admin/assets/js/vendor/codemirror/test/index.html +209 -0
  321. data/core/admin/assets/js/vendor/codemirror/test/lint/acorn.js +1593 -0
  322. data/core/admin/assets/js/vendor/codemirror/test/lint/lint.js +139 -0
  323. data/core/admin/assets/js/vendor/codemirror/test/lint/walk.js +216 -0
  324. data/core/admin/assets/js/vendor/codemirror/test/mode_test.css +10 -0
  325. data/core/admin/assets/js/vendor/codemirror/test/mode_test.js +200 -0
  326. data/core/admin/assets/js/vendor/codemirror/test/phantom_driver.js +31 -0
  327. data/core/admin/assets/js/vendor/codemirror/test/run.js +34 -0
  328. data/core/admin/assets/js/vendor/codemirror/test/test.js +1562 -0
  329. data/core/admin/assets/js/vendor/codemirror/test/vim_test.js +2391 -0
  330. data/core/admin/assets/js/vendor/codemirror/theme/3024-day.css +34 -0
  331. data/core/admin/assets/js/vendor/codemirror/theme/3024-night.css +34 -0
  332. data/core/admin/assets/js/vendor/codemirror/theme/ambiance-mobile.css +5 -0
  333. data/core/admin/assets/js/vendor/codemirror/theme/ambiance.css +75 -0
  334. data/core/admin/assets/js/vendor/codemirror/theme/base16-dark.css +34 -0
  335. data/core/admin/assets/js/vendor/codemirror/theme/base16-light.css +34 -0
  336. data/core/admin/assets/js/vendor/codemirror/theme/blackboard.css +28 -0
  337. data/core/admin/assets/js/vendor/codemirror/theme/cobalt.css +21 -0
  338. data/core/admin/assets/js/vendor/codemirror/theme/eclipse.css +23 -0
  339. data/core/admin/assets/js/vendor/codemirror/theme/elegant.css +13 -0
  340. data/core/admin/assets/js/vendor/codemirror/theme/erlang-dark.css +30 -0
  341. data/core/admin/assets/js/vendor/codemirror/theme/lesser-dark.css +47 -0
  342. data/core/admin/assets/js/vendor/codemirror/theme/mbo.css +35 -0
  343. data/core/admin/assets/js/vendor/codemirror/theme/midnight.css +43 -0
  344. data/core/admin/assets/js/vendor/codemirror/theme/monokai.css +29 -0
  345. data/core/admin/assets/js/vendor/codemirror/theme/neat.css +12 -0
  346. data/core/admin/assets/js/vendor/codemirror/theme/night.css +24 -0
  347. data/core/admin/assets/js/vendor/codemirror/theme/paraiso-dark.css +34 -0
  348. data/core/admin/assets/js/vendor/codemirror/theme/paraiso-light.css +34 -0
  349. data/core/admin/assets/js/vendor/codemirror/theme/rubyblue.css +23 -0
  350. data/core/admin/assets/js/vendor/codemirror/theme/solarized-mod.css +181 -0
  351. data/core/admin/assets/js/vendor/codemirror/theme/solarized.css +180 -0
  352. data/core/admin/assets/js/vendor/codemirror/theme/the-matrix.css +26 -0
  353. data/core/admin/assets/js/vendor/codemirror/theme/tomorrow-night-eighties.css +34 -0
  354. data/core/admin/assets/js/vendor/codemirror/theme/twilight.css +28 -0
  355. data/core/admin/assets/js/vendor/codemirror/theme/vibrant-ink.css +30 -0
  356. data/core/admin/assets/js/vendor/codemirror/theme/xq-dark.css +49 -0
  357. data/core/admin/assets/js/vendor/codemirror/theme/xq-light.css +43 -0
  358. data/core/admin/assets/js/vendor/fastclick.js +777 -0
  359. data/core/admin/assets/js/vendor/jquery.js +6 -0
  360. data/core/admin/assets/js/vendor/lodash.underscore.js +38 -0
  361. data/core/admin/assets/js/vendor/require.js +36 -0
  362. data/core/admin/assets/scss/bootstrap.scss +18 -0
  363. data/core/admin/assets/scss/modules/_all.scss +7 -0
  364. data/core/admin/assets/scss/modules/_colors.scss +7 -0
  365. data/core/admin/assets/scss/modules/_extensions.scss +24 -0
  366. data/core/admin/assets/scss/modules/_mixins.scss +18 -0
  367. data/core/admin/assets/scss/modules/_susy.scss +7 -0
  368. data/core/admin/assets/scss/partials/_base.scss +33 -0
  369. data/core/admin/assets/scss/partials/_buttons.scss +9 -0
  370. data/core/admin/assets/scss/partials/_links.scss +15 -0
  371. data/core/admin/assets/scss/partials/_main.scss +14 -0
  372. data/core/admin/assets/scss/partials/_typography.scss +15 -0
  373. data/core/admin/assets/scss/sections/_editor.scss +274 -0
  374. data/core/admin/assets/scss/sections/_login.scss +34 -0
  375. data/core/admin/assets/scss/vendor/_normalize.scss +406 -0
  376. data/core/admin/layouts/admin.haml +67 -0
  377. data/core/admin/partials/_head.haml +23 -0
  378. data/core/admin/partials/_tree.haml +3 -0
  379. data/core/admin/partials/_treeitem.haml +4 -0
  380. data/core/admin/settings.yml +4 -0
  381. data/core/app.rb +21 -0
  382. data/core/classes/cached.rb +35 -0
  383. data/core/classes/checker.rb +37 -0
  384. data/core/classes/commit.rb +62 -0
  385. data/core/classes/error.rb +9 -0
  386. data/core/classes/page.rb +165 -0
  387. data/core/classes/partial.rb +13 -0
  388. data/core/classes/path.rb +30 -0
  389. data/core/classes/persona.rb +55 -0
  390. data/core/classes/sassfile.rb +95 -0
  391. data/core/classes/settings.rb +19 -0
  392. data/core/classes/theme.rb +55 -0
  393. data/core/helpers/base.rb +46 -0
  394. data/core/helpers/render.rb +26 -0
  395. data/core/helpers/truncate.rb +17 -0
  396. data/core/routes/admin.rb +139 -0
  397. data/core/routes/assetcompiler.rb +23 -0
  398. data/core/routes/base.rb +22 -0
  399. data/core/routes/bootstrap.rb +35 -0
  400. data/core/routes/cache.rb +52 -0
  401. data/core/routes/deploy.rb +16 -0
  402. data/core/routes/git.rb +23 -0
  403. data/poly.gemspec +29 -0
  404. data/sample/.cabi-data +0 -0
  405. data/sample/data/home/index.haml +22 -0
  406. data/sample/data/other/nav/links.yml +4 -0
  407. data/sample/data/page/about/index.haml +12 -0
  408. data/sample/data/page/contact-us/index.haml +11 -0
  409. data/sample/data/page/dynamic-page/index.haml +14 -0
  410. data/sample/data/page/error/index.haml +8 -0
  411. data/sample/data/page/html/index.html +4 -0
  412. data/sample/data/page/no-front-matter/index.haml +7 -0
  413. data/sample/data/page/not-found/index.haml +8 -0
  414. data/sample/data/page/static-page/index.haml +14 -0
  415. data/sample/data/post/about-life/index.md +12 -0
  416. data/sample/data/post/sample-post/index.haml +12 -0
  417. data/sample/data/post/technology/index.haml +12 -0
  418. data/sample/data/post/the-40-hour-workweek/index.haml +9 -0
  419. data/sample/data/post/things-are-changing/index.haml +9 -0
  420. data/sample/data/post/yet-another-post/index.haml +11 -0
  421. data/sample/plugins/my-plugin/plugin.rb +15 -0
  422. data/sample/settings.yml +21 -0
  423. data/sample/themes/base/assets/css/readme.txt +6 -0
  424. data/sample/themes/base/assets/images/poly.svg +36 -0
  425. data/sample/themes/base/assets/js/app/views/main.js +13 -0
  426. data/sample/themes/base/assets/js/main.js +31 -0
  427. data/sample/themes/base/assets/js/vendor/backbone.js +4 -0
  428. data/sample/themes/base/assets/js/vendor/jquery.js +6 -0
  429. data/sample/themes/base/assets/js/vendor/lodash.underscore.js +38 -0
  430. data/sample/themes/base/assets/js/vendor/require.js +36 -0
  431. data/sample/themes/base/assets/scss/bootstrap.scss +20 -0
  432. data/sample/themes/base/assets/scss/modules/_all.scss +7 -0
  433. data/sample/themes/base/assets/scss/modules/_colors.scss +7 -0
  434. data/sample/themes/base/assets/scss/modules/_extensions.scss +13 -0
  435. data/sample/themes/base/assets/scss/modules/_mixins.scss +11 -0
  436. data/sample/themes/base/assets/scss/modules/_susy.scss +7 -0
  437. data/sample/themes/base/assets/scss/partials/_base.scss +33 -0
  438. data/sample/themes/base/assets/scss/partials/_buttons.scss +0 -0
  439. data/sample/themes/base/assets/scss/partials/_links.scss +15 -0
  440. data/sample/themes/base/assets/scss/partials/_main.scss +39 -0
  441. data/sample/themes/base/assets/scss/partials/_typography.scss +15 -0
  442. data/sample/themes/base/assets/scss/sections/_footer.scss +22 -0
  443. data/sample/themes/base/assets/scss/sections/_header.scss +23 -0
  444. data/sample/themes/base/assets/scss/sections/_home.scss +13 -0
  445. data/sample/themes/base/assets/scss/sections/_pages.scss +11 -0
  446. data/sample/themes/base/assets/scss/vendor/_normalize.scss +406 -0
  447. data/sample/themes/base/layouts/default.haml +14 -0
  448. data/sample/themes/base/layouts/post.haml +15 -0
  449. data/sample/themes/base/partials/_footer.haml +9 -0
  450. data/sample/themes/base/partials/_ga.haml +10 -0
  451. data/sample/themes/base/partials/_head.haml +20 -0
  452. data/sample/themes/base/partials/_header.haml +5 -0
  453. data/sample/themes/base/settings.yml +4 -0
  454. data/test/data/post-receive-hook.json +146 -0
  455. data/test/test_basics.rb +50 -0
  456. data/test/test_data.rb +14 -0
  457. data/test/test_deploy.rb +23 -0
  458. data/test/test_includes.rb +43 -0
  459. data/test/test_page.rb +47 -0
  460. metadata +1049 -0
@@ -0,0 +1,31 @@
1
+ var page = require('webpage').create();
2
+
3
+ page.open("http://localhost:3000/test/index.html", function (status) {
4
+ if (status != "success") {
5
+ console.log("page couldn't be loaded successfully");
6
+ phantom.exit(1);
7
+ }
8
+ waitFor(function () {
9
+ return page.evaluate(function () {
10
+ var output = document.getElementById('status');
11
+ if (!output) { return false; }
12
+ return (/^(\d+ failures?|all passed)/i).test(output.innerText);
13
+ });
14
+ }, function () {
15
+ var failed = page.evaluate(function () { return window.failed; });
16
+ var output = page.evaluate(function () {
17
+ return document.getElementById('output').innerText + "\n" +
18
+ document.getElementById('status').innerText;
19
+ });
20
+ console.log(output);
21
+ phantom.exit(failed > 0 ? 1 : 0);
22
+ });
23
+ });
24
+
25
+ function waitFor (test, cb) {
26
+ if (test()) {
27
+ cb();
28
+ } else {
29
+ setTimeout(function () { waitFor(test, cb); }, 250);
30
+ }
31
+ }
@@ -0,0 +1,34 @@
1
+ #!/usr/bin/env node
2
+
3
+ var lint = require("./lint/lint");
4
+
5
+ lint.checkDir("mode");
6
+ lint.checkDir("lib");
7
+ lint.checkDir("addon");
8
+ lint.checkDir("keymap");
9
+
10
+ var ok = lint.success();
11
+
12
+ var files = new (require('node-static').Server)('.');
13
+
14
+ var server = require('http').createServer(function (req, res) {
15
+ req.addListener('end', function () {
16
+ files.serve(req, res);
17
+ });
18
+ }).addListener('error', function (err) {
19
+ throw err;
20
+ }).listen(3000, function () {
21
+ var child_process = require('child_process');
22
+ child_process.exec("which phantomjs", function (err) {
23
+ if (err) {
24
+ console.error("PhantomJS is not installed. Download from http://phantomjs.org");
25
+ process.exit(1);
26
+ }
27
+ var cmd = 'phantomjs test/phantom_driver.js';
28
+ child_process.exec(cmd, function (err, stdout) {
29
+ server.close();
30
+ console.log(stdout);
31
+ process.exit(err || !ok ? 1 : 0);
32
+ });
33
+ });
34
+ });
@@ -0,0 +1,1562 @@
1
+ var Pos = CodeMirror.Pos;
2
+
3
+ CodeMirror.defaults.rtlMoveVisually = true;
4
+
5
+ function forEach(arr, f) {
6
+ for (var i = 0, e = arr.length; i < e; ++i) f(arr[i]);
7
+ }
8
+
9
+ function addDoc(cm, width, height) {
10
+ var content = [], line = "";
11
+ for (var i = 0; i < width; ++i) line += "x";
12
+ for (var i = 0; i < height; ++i) content.push(line);
13
+ cm.setValue(content.join("\n"));
14
+ }
15
+
16
+ function byClassName(elt, cls) {
17
+ if (elt.getElementsByClassName) return elt.getElementsByClassName(cls);
18
+ var found = [], re = new RegExp("\\b" + cls + "\\b");
19
+ function search(elt) {
20
+ if (elt.nodeType == 3) return;
21
+ if (re.test(elt.className)) found.push(elt);
22
+ for (var i = 0, e = elt.childNodes.length; i < e; ++i)
23
+ search(elt.childNodes[i]);
24
+ }
25
+ search(elt);
26
+ return found;
27
+ }
28
+
29
+ var ie_lt8 = /MSIE [1-7]\b/.test(navigator.userAgent);
30
+ var mac = /Mac/.test(navigator.platform);
31
+ var phantom = /PhantomJS/.test(navigator.userAgent);
32
+ var opera = /Opera\/\./.test(navigator.userAgent);
33
+ var opera_version = opera && navigator.userAgent.match(/Version\/(\d+\.\d+)/);
34
+ if (opera_version) opera_version = Number(opera_version);
35
+ var opera_lt10 = opera && (!opera_version || opera_version < 10);
36
+
37
+ namespace = "core_";
38
+
39
+ test("core_fromTextArea", function() {
40
+ var te = document.getElementById("code");
41
+ te.value = "CONTENT";
42
+ var cm = CodeMirror.fromTextArea(te);
43
+ is(!te.offsetHeight);
44
+ eq(cm.getValue(), "CONTENT");
45
+ cm.setValue("foo\nbar");
46
+ eq(cm.getValue(), "foo\nbar");
47
+ cm.save();
48
+ is(/^foo\r?\nbar$/.test(te.value));
49
+ cm.setValue("xxx");
50
+ cm.toTextArea();
51
+ is(te.offsetHeight);
52
+ eq(te.value, "xxx");
53
+ });
54
+
55
+ testCM("getRange", function(cm) {
56
+ eq(cm.getLine(0), "1234");
57
+ eq(cm.getLine(1), "5678");
58
+ eq(cm.getLine(2), null);
59
+ eq(cm.getLine(-1), null);
60
+ eq(cm.getRange(Pos(0, 0), Pos(0, 3)), "123");
61
+ eq(cm.getRange(Pos(0, -1), Pos(0, 200)), "1234");
62
+ eq(cm.getRange(Pos(0, 2), Pos(1, 2)), "34\n56");
63
+ eq(cm.getRange(Pos(1, 2), Pos(100, 0)), "78");
64
+ }, {value: "1234\n5678"});
65
+
66
+ testCM("replaceRange", function(cm) {
67
+ eq(cm.getValue(), "");
68
+ cm.replaceRange("foo\n", Pos(0, 0));
69
+ eq(cm.getValue(), "foo\n");
70
+ cm.replaceRange("a\nb", Pos(0, 1));
71
+ eq(cm.getValue(), "fa\nboo\n");
72
+ eq(cm.lineCount(), 3);
73
+ cm.replaceRange("xyzzy", Pos(0, 0), Pos(1, 1));
74
+ eq(cm.getValue(), "xyzzyoo\n");
75
+ cm.replaceRange("abc", Pos(0, 0), Pos(10, 0));
76
+ eq(cm.getValue(), "abc");
77
+ eq(cm.lineCount(), 1);
78
+ });
79
+
80
+ testCM("selection", function(cm) {
81
+ cm.setSelection(Pos(0, 4), Pos(2, 2));
82
+ is(cm.somethingSelected());
83
+ eq(cm.getSelection(), "11\n222222\n33");
84
+ eqPos(cm.getCursor(false), Pos(2, 2));
85
+ eqPos(cm.getCursor(true), Pos(0, 4));
86
+ cm.setSelection(Pos(1, 0));
87
+ is(!cm.somethingSelected());
88
+ eq(cm.getSelection(), "");
89
+ eqPos(cm.getCursor(true), Pos(1, 0));
90
+ cm.replaceSelection("abc");
91
+ eq(cm.getSelection(), "abc");
92
+ eq(cm.getValue(), "111111\nabc222222\n333333");
93
+ cm.replaceSelection("def", "end");
94
+ eq(cm.getSelection(), "");
95
+ eqPos(cm.getCursor(true), Pos(1, 3));
96
+ cm.setCursor(Pos(2, 1));
97
+ eqPos(cm.getCursor(true), Pos(2, 1));
98
+ cm.setCursor(1, 2);
99
+ eqPos(cm.getCursor(true), Pos(1, 2));
100
+ }, {value: "111111\n222222\n333333"});
101
+
102
+ testCM("extendSelection", function(cm) {
103
+ cm.setExtending(true);
104
+ addDoc(cm, 10, 10);
105
+ cm.setSelection(Pos(3, 5));
106
+ eqPos(cm.getCursor("head"), Pos(3, 5));
107
+ eqPos(cm.getCursor("anchor"), Pos(3, 5));
108
+ cm.setSelection(Pos(2, 5), Pos(5, 5));
109
+ eqPos(cm.getCursor("head"), Pos(5, 5));
110
+ eqPos(cm.getCursor("anchor"), Pos(2, 5));
111
+ eqPos(cm.getCursor("start"), Pos(2, 5));
112
+ eqPos(cm.getCursor("end"), Pos(5, 5));
113
+ cm.setSelection(Pos(5, 5), Pos(2, 5));
114
+ eqPos(cm.getCursor("head"), Pos(2, 5));
115
+ eqPos(cm.getCursor("anchor"), Pos(5, 5));
116
+ eqPos(cm.getCursor("start"), Pos(2, 5));
117
+ eqPos(cm.getCursor("end"), Pos(5, 5));
118
+ cm.extendSelection(Pos(3, 2));
119
+ eqPos(cm.getCursor("head"), Pos(3, 2));
120
+ eqPos(cm.getCursor("anchor"), Pos(5, 5));
121
+ cm.extendSelection(Pos(6, 2));
122
+ eqPos(cm.getCursor("head"), Pos(6, 2));
123
+ eqPos(cm.getCursor("anchor"), Pos(5, 5));
124
+ cm.extendSelection(Pos(6, 3), Pos(6, 4));
125
+ eqPos(cm.getCursor("head"), Pos(6, 4));
126
+ eqPos(cm.getCursor("anchor"), Pos(5, 5));
127
+ cm.extendSelection(Pos(0, 3), Pos(0, 4));
128
+ eqPos(cm.getCursor("head"), Pos(0, 3));
129
+ eqPos(cm.getCursor("anchor"), Pos(5, 5));
130
+ cm.extendSelection(Pos(4, 5), Pos(6, 5));
131
+ eqPos(cm.getCursor("head"), Pos(6, 5));
132
+ eqPos(cm.getCursor("anchor"), Pos(4, 5));
133
+ cm.setExtending(false);
134
+ cm.extendSelection(Pos(0, 3), Pos(0, 4));
135
+ eqPos(cm.getCursor("head"), Pos(0, 4));
136
+ eqPos(cm.getCursor("anchor"), Pos(0, 3));
137
+ });
138
+
139
+ testCM("lines", function(cm) {
140
+ eq(cm.getLine(0), "111111");
141
+ eq(cm.getLine(1), "222222");
142
+ eq(cm.getLine(-1), null);
143
+ cm.removeLine(1);
144
+ cm.setLine(1, "abc");
145
+ eq(cm.getValue(), "111111\nabc");
146
+ }, {value: "111111\n222222\n333333"});
147
+
148
+ testCM("indent", function(cm) {
149
+ cm.indentLine(1);
150
+ eq(cm.getLine(1), " blah();");
151
+ cm.setOption("indentUnit", 8);
152
+ cm.indentLine(1);
153
+ eq(cm.getLine(1), "\tblah();");
154
+ cm.setOption("indentUnit", 10);
155
+ cm.setOption("tabSize", 4);
156
+ cm.indentLine(1);
157
+ eq(cm.getLine(1), "\t\t blah();");
158
+ }, {value: "if (x) {\nblah();\n}", indentUnit: 3, indentWithTabs: true, tabSize: 8});
159
+
160
+ testCM("indentByNumber", function(cm) {
161
+ cm.indentLine(0, 2);
162
+ eq(cm.getLine(0), " foo");
163
+ cm.indentLine(0, -200);
164
+ eq(cm.getLine(0), "foo");
165
+ cm.setSelection(Pos(0, 0), Pos(1, 2));
166
+ cm.indentSelection(3);
167
+ eq(cm.getValue(), " foo\n bar\nbaz");
168
+ }, {value: "foo\nbar\nbaz"});
169
+
170
+ test("core_defaults", function() {
171
+ var defsCopy = {}, defs = CodeMirror.defaults;
172
+ for (var opt in defs) defsCopy[opt] = defs[opt];
173
+ defs.indentUnit = 5;
174
+ defs.value = "uu";
175
+ defs.enterMode = "keep";
176
+ defs.tabindex = 55;
177
+ var place = document.getElementById("testground"), cm = CodeMirror(place);
178
+ try {
179
+ eq(cm.getOption("indentUnit"), 5);
180
+ cm.setOption("indentUnit", 10);
181
+ eq(defs.indentUnit, 5);
182
+ eq(cm.getValue(), "uu");
183
+ eq(cm.getOption("enterMode"), "keep");
184
+ eq(cm.getInputField().tabIndex, 55);
185
+ }
186
+ finally {
187
+ for (var opt in defsCopy) defs[opt] = defsCopy[opt];
188
+ place.removeChild(cm.getWrapperElement());
189
+ }
190
+ });
191
+
192
+ testCM("lineInfo", function(cm) {
193
+ eq(cm.lineInfo(-1), null);
194
+ var mark = document.createElement("span");
195
+ var lh = cm.setGutterMarker(1, "FOO", mark);
196
+ var info = cm.lineInfo(1);
197
+ eq(info.text, "222222");
198
+ eq(info.gutterMarkers.FOO, mark);
199
+ eq(info.line, 1);
200
+ eq(cm.lineInfo(2).gutterMarkers, null);
201
+ cm.setGutterMarker(lh, "FOO", null);
202
+ eq(cm.lineInfo(1).gutterMarkers, null);
203
+ cm.setGutterMarker(1, "FOO", mark);
204
+ cm.setGutterMarker(0, "FOO", mark);
205
+ cm.clearGutter("FOO");
206
+ eq(cm.lineInfo(0).gutterMarkers, null);
207
+ eq(cm.lineInfo(1).gutterMarkers, null);
208
+ }, {value: "111111\n222222\n333333"});
209
+
210
+ testCM("coords", function(cm) {
211
+ cm.setSize(null, 100);
212
+ addDoc(cm, 32, 200);
213
+ var top = cm.charCoords(Pos(0, 0));
214
+ var bot = cm.charCoords(Pos(200, 30));
215
+ is(top.left < bot.left);
216
+ is(top.top < bot.top);
217
+ is(top.top < top.bottom);
218
+ cm.scrollTo(null, 100);
219
+ var top2 = cm.charCoords(Pos(0, 0));
220
+ is(top.top > top2.top);
221
+ eq(top.left, top2.left);
222
+ });
223
+
224
+ testCM("coordsChar", function(cm) {
225
+ addDoc(cm, 35, 70);
226
+ for (var i = 0; i < 2; ++i) {
227
+ var sys = i ? "local" : "page";
228
+ for (var ch = 0; ch <= 35; ch += 5) {
229
+ for (var line = 0; line < 70; line += 5) {
230
+ cm.setCursor(line, ch);
231
+ var coords = cm.charCoords(Pos(line, ch), sys);
232
+ var pos = cm.coordsChar({left: coords.left + 1, top: coords.top + 1}, sys);
233
+ eqPos(pos, Pos(line, ch));
234
+ }
235
+ }
236
+ }
237
+ }, {lineNumbers: true});
238
+
239
+ testCM("posFromIndex", function(cm) {
240
+ cm.setValue(
241
+ "This function should\n" +
242
+ "convert a zero based index\n" +
243
+ "to line and ch."
244
+ );
245
+
246
+ var examples = [
247
+ { index: -1, line: 0, ch: 0 }, // <- Tests clipping
248
+ { index: 0, line: 0, ch: 0 },
249
+ { index: 10, line: 0, ch: 10 },
250
+ { index: 39, line: 1, ch: 18 },
251
+ { index: 55, line: 2, ch: 7 },
252
+ { index: 63, line: 2, ch: 15 },
253
+ { index: 64, line: 2, ch: 15 } // <- Tests clipping
254
+ ];
255
+
256
+ for (var i = 0; i < examples.length; i++) {
257
+ var example = examples[i];
258
+ var pos = cm.posFromIndex(example.index);
259
+ eq(pos.line, example.line);
260
+ eq(pos.ch, example.ch);
261
+ if (example.index >= 0 && example.index < 64)
262
+ eq(cm.indexFromPos(pos), example.index);
263
+ }
264
+ });
265
+
266
+ testCM("undo", function(cm) {
267
+ cm.setLine(0, "def");
268
+ eq(cm.historySize().undo, 1);
269
+ cm.undo();
270
+ eq(cm.getValue(), "abc");
271
+ eq(cm.historySize().undo, 0);
272
+ eq(cm.historySize().redo, 1);
273
+ cm.redo();
274
+ eq(cm.getValue(), "def");
275
+ eq(cm.historySize().undo, 1);
276
+ eq(cm.historySize().redo, 0);
277
+ cm.setValue("1\n\n\n2");
278
+ cm.clearHistory();
279
+ eq(cm.historySize().undo, 0);
280
+ for (var i = 0; i < 20; ++i) {
281
+ cm.replaceRange("a", Pos(0, 0));
282
+ cm.replaceRange("b", Pos(3, 0));
283
+ }
284
+ eq(cm.historySize().undo, 40);
285
+ for (var i = 0; i < 40; ++i)
286
+ cm.undo();
287
+ eq(cm.historySize().redo, 40);
288
+ eq(cm.getValue(), "1\n\n\n2");
289
+ }, {value: "abc"});
290
+
291
+ testCM("undoDepth", function(cm) {
292
+ cm.replaceRange("d", Pos(0));
293
+ cm.replaceRange("e", Pos(0));
294
+ cm.replaceRange("f", Pos(0));
295
+ cm.undo(); cm.undo(); cm.undo();
296
+ eq(cm.getValue(), "abcd");
297
+ }, {value: "abc", undoDepth: 2});
298
+
299
+ testCM("undoDoesntClearValue", function(cm) {
300
+ cm.undo();
301
+ eq(cm.getValue(), "x");
302
+ }, {value: "x"});
303
+
304
+ testCM("undoMultiLine", function(cm) {
305
+ cm.operation(function() {
306
+ cm.replaceRange("x", Pos(0, 0));
307
+ cm.replaceRange("y", Pos(1, 0));
308
+ });
309
+ cm.undo();
310
+ eq(cm.getValue(), "abc\ndef\nghi");
311
+ cm.operation(function() {
312
+ cm.replaceRange("y", Pos(1, 0));
313
+ cm.replaceRange("x", Pos(0, 0));
314
+ });
315
+ cm.undo();
316
+ eq(cm.getValue(), "abc\ndef\nghi");
317
+ cm.operation(function() {
318
+ cm.replaceRange("y", Pos(2, 0));
319
+ cm.replaceRange("x", Pos(1, 0));
320
+ cm.replaceRange("z", Pos(2, 0));
321
+ });
322
+ cm.undo();
323
+ eq(cm.getValue(), "abc\ndef\nghi", 3);
324
+ }, {value: "abc\ndef\nghi"});
325
+
326
+ testCM("undoComposite", function(cm) {
327
+ cm.replaceRange("y", Pos(1));
328
+ cm.operation(function() {
329
+ cm.replaceRange("x", Pos(0));
330
+ cm.replaceRange("z", Pos(2));
331
+ });
332
+ eq(cm.getValue(), "ax\nby\ncz\n");
333
+ cm.undo();
334
+ eq(cm.getValue(), "a\nby\nc\n");
335
+ cm.undo();
336
+ eq(cm.getValue(), "a\nb\nc\n");
337
+ cm.redo(); cm.redo();
338
+ eq(cm.getValue(), "ax\nby\ncz\n");
339
+ }, {value: "a\nb\nc\n"});
340
+
341
+ testCM("undoSelection", function(cm) {
342
+ cm.setSelection(Pos(0, 2), Pos(0, 4));
343
+ cm.replaceSelection("");
344
+ cm.setCursor(Pos(1, 0));
345
+ cm.undo();
346
+ eqPos(cm.getCursor(true), Pos(0, 2));
347
+ eqPos(cm.getCursor(false), Pos(0, 4));
348
+ cm.setCursor(Pos(1, 0));
349
+ cm.redo();
350
+ eqPos(cm.getCursor(true), Pos(0, 2));
351
+ eqPos(cm.getCursor(false), Pos(0, 2));
352
+ }, {value: "abcdefgh\n"});
353
+
354
+ testCM("markTextSingleLine", function(cm) {
355
+ forEach([{a: 0, b: 1, c: "", f: 2, t: 5},
356
+ {a: 0, b: 4, c: "", f: 0, t: 2},
357
+ {a: 1, b: 2, c: "x", f: 3, t: 6},
358
+ {a: 4, b: 5, c: "", f: 3, t: 5},
359
+ {a: 4, b: 5, c: "xx", f: 3, t: 7},
360
+ {a: 2, b: 5, c: "", f: 2, t: 3},
361
+ {a: 2, b: 5, c: "abcd", f: 6, t: 7},
362
+ {a: 2, b: 6, c: "x", f: null, t: null},
363
+ {a: 3, b: 6, c: "", f: null, t: null},
364
+ {a: 0, b: 9, c: "hallo", f: null, t: null},
365
+ {a: 4, b: 6, c: "x", f: 3, t: 4},
366
+ {a: 4, b: 8, c: "", f: 3, t: 4},
367
+ {a: 6, b: 6, c: "a", f: 3, t: 6},
368
+ {a: 8, b: 9, c: "", f: 3, t: 6}], function(test) {
369
+ cm.setValue("1234567890");
370
+ var r = cm.markText(Pos(0, 3), Pos(0, 6), {className: "foo"});
371
+ cm.replaceRange(test.c, Pos(0, test.a), Pos(0, test.b));
372
+ var f = r.find();
373
+ eq(f && f.from.ch, test.f); eq(f && f.to.ch, test.t);
374
+ });
375
+ });
376
+
377
+ testCM("markTextMultiLine", function(cm) {
378
+ function p(v) { return v && Pos(v[0], v[1]); }
379
+ forEach([{a: [0, 0], b: [0, 5], c: "", f: [0, 0], t: [2, 5]},
380
+ {a: [0, 0], b: [0, 5], c: "foo\n", f: [1, 0], t: [3, 5]},
381
+ {a: [0, 1], b: [0, 10], c: "", f: [0, 1], t: [2, 5]},
382
+ {a: [0, 5], b: [0, 6], c: "x", f: [0, 6], t: [2, 5]},
383
+ {a: [0, 0], b: [1, 0], c: "", f: [0, 0], t: [1, 5]},
384
+ {a: [0, 6], b: [2, 4], c: "", f: [0, 5], t: [0, 7]},
385
+ {a: [0, 6], b: [2, 4], c: "aa", f: [0, 5], t: [0, 9]},
386
+ {a: [1, 2], b: [1, 8], c: "", f: [0, 5], t: [2, 5]},
387
+ {a: [0, 5], b: [2, 5], c: "xx", f: null, t: null},
388
+ {a: [0, 0], b: [2, 10], c: "x", f: null, t: null},
389
+ {a: [1, 5], b: [2, 5], c: "", f: [0, 5], t: [1, 5]},
390
+ {a: [2, 0], b: [2, 3], c: "", f: [0, 5], t: [2, 2]},
391
+ {a: [2, 5], b: [3, 0], c: "a\nb", f: [0, 5], t: [2, 5]},
392
+ {a: [2, 3], b: [3, 0], c: "x", f: [0, 5], t: [2, 3]},
393
+ {a: [1, 1], b: [1, 9], c: "1\n2\n3", f: [0, 5], t: [4, 5]}], function(test) {
394
+ cm.setValue("aaaaaaaaaa\nbbbbbbbbbb\ncccccccccc\ndddddddd\n");
395
+ var r = cm.markText(Pos(0, 5), Pos(2, 5),
396
+ {className: "CodeMirror-matchingbracket"});
397
+ cm.replaceRange(test.c, p(test.a), p(test.b));
398
+ var f = r.find();
399
+ eqPos(f && f.from, p(test.f)); eqPos(f && f.to, p(test.t));
400
+ });
401
+ });
402
+
403
+ testCM("markTextUndo", function(cm) {
404
+ var marker1, marker2, bookmark;
405
+ marker1 = cm.markText(Pos(0, 1), Pos(0, 3),
406
+ {className: "CodeMirror-matchingbracket"});
407
+ marker2 = cm.markText(Pos(0, 0), Pos(2, 1),
408
+ {className: "CodeMirror-matchingbracket"});
409
+ bookmark = cm.setBookmark(Pos(1, 5));
410
+ cm.operation(function(){
411
+ cm.replaceRange("foo", Pos(0, 2));
412
+ cm.replaceRange("bar\nbaz\nbug\n", Pos(2, 0), Pos(3, 0));
413
+ });
414
+ var v1 = cm.getValue();
415
+ cm.setValue("");
416
+ eq(marker1.find(), null); eq(marker2.find(), null); eq(bookmark.find(), null);
417
+ cm.undo();
418
+ eqPos(bookmark.find(), Pos(1, 5), "still there");
419
+ cm.undo();
420
+ var m1Pos = marker1.find(), m2Pos = marker2.find();
421
+ eqPos(m1Pos.from, Pos(0, 1)); eqPos(m1Pos.to, Pos(0, 3));
422
+ eqPos(m2Pos.from, Pos(0, 0)); eqPos(m2Pos.to, Pos(2, 1));
423
+ eqPos(bookmark.find(), Pos(1, 5));
424
+ cm.redo(); cm.redo();
425
+ eq(bookmark.find(), null);
426
+ cm.undo();
427
+ eqPos(bookmark.find(), Pos(1, 5));
428
+ eq(cm.getValue(), v1);
429
+ }, {value: "1234\n56789\n00\n"});
430
+
431
+ testCM("markTextStayGone", function(cm) {
432
+ var m1 = cm.markText(Pos(0, 0), Pos(0, 1));
433
+ cm.replaceRange("hi", Pos(0, 2));
434
+ m1.clear();
435
+ cm.undo();
436
+ eq(m1.find(), null);
437
+ }, {value: "hello"});
438
+
439
+ testCM("undoPreservesNewMarks", function(cm) {
440
+ cm.markText(Pos(0, 3), Pos(0, 4));
441
+ cm.markText(Pos(1, 1), Pos(1, 3));
442
+ cm.replaceRange("", Pos(0, 3), Pos(3, 1));
443
+ var mBefore = cm.markText(Pos(0, 0), Pos(0, 1));
444
+ var mAfter = cm.markText(Pos(0, 5), Pos(0, 6));
445
+ var mAround = cm.markText(Pos(0, 2), Pos(0, 4));
446
+ cm.undo();
447
+ eqPos(mBefore.find().from, Pos(0, 0));
448
+ eqPos(mBefore.find().to, Pos(0, 1));
449
+ eqPos(mAfter.find().from, Pos(3, 3));
450
+ eqPos(mAfter.find().to, Pos(3, 4));
451
+ eqPos(mAround.find().from, Pos(0, 2));
452
+ eqPos(mAround.find().to, Pos(3, 2));
453
+ var found = cm.findMarksAt(Pos(2, 2));
454
+ eq(found.length, 1);
455
+ eq(found[0], mAround);
456
+ }, {value: "aaaa\nbbbb\ncccc\ndddd"});
457
+
458
+ testCM("markClearBetween", function(cm) {
459
+ cm.setValue("aaa\nbbb\nccc\nddd\n");
460
+ cm.markText(Pos(0, 0), Pos(2));
461
+ cm.replaceRange("aaa\nbbb\nccc", Pos(0, 0), Pos(2));
462
+ eq(cm.findMarksAt(Pos(1, 1)).length, 0);
463
+ });
464
+
465
+ testCM("deleteSpanCollapsedInclusiveLeft", function(cm) {
466
+ var from = Pos(1, 0), to = Pos(1, 1);
467
+ var m = cm.markText(from, to, {collapsed: true, inclusiveLeft: true});
468
+ // Delete collapsed span.
469
+ cm.replaceRange("", from, to);
470
+ }, {value: "abc\nX\ndef"});
471
+
472
+ testCM("bookmark", function(cm) {
473
+ function p(v) { return v && Pos(v[0], v[1]); }
474
+ forEach([{a: [1, 0], b: [1, 1], c: "", d: [1, 4]},
475
+ {a: [1, 1], b: [1, 1], c: "xx", d: [1, 7]},
476
+ {a: [1, 4], b: [1, 5], c: "ab", d: [1, 6]},
477
+ {a: [1, 4], b: [1, 6], c: "", d: null},
478
+ {a: [1, 5], b: [1, 6], c: "abc", d: [1, 5]},
479
+ {a: [1, 6], b: [1, 8], c: "", d: [1, 5]},
480
+ {a: [1, 4], b: [1, 4], c: "\n\n", d: [3, 1]},
481
+ {bm: [1, 9], a: [1, 1], b: [1, 1], c: "\n", d: [2, 8]}], function(test) {
482
+ cm.setValue("1234567890\n1234567890\n1234567890");
483
+ var b = cm.setBookmark(p(test.bm) || Pos(1, 5));
484
+ cm.replaceRange(test.c, p(test.a), p(test.b));
485
+ eqPos(b.find(), p(test.d));
486
+ });
487
+ });
488
+
489
+ testCM("bookmarkInsertLeft", function(cm) {
490
+ var br = cm.setBookmark(Pos(0, 2), {insertLeft: false});
491
+ var bl = cm.setBookmark(Pos(0, 2), {insertLeft: true});
492
+ cm.setCursor(Pos(0, 2));
493
+ cm.replaceSelection("hi");
494
+ eqPos(br.find(), Pos(0, 2));
495
+ eqPos(bl.find(), Pos(0, 4));
496
+ cm.replaceRange("", Pos(0, 4), Pos(0, 5));
497
+ cm.replaceRange("", Pos(0, 2), Pos(0, 4));
498
+ cm.replaceRange("", Pos(0, 1), Pos(0, 2));
499
+ // Verify that deleting next to bookmarks doesn't kill them
500
+ eqPos(br.find(), Pos(0, 1));
501
+ eqPos(bl.find(), Pos(0, 1));
502
+ }, {value: "abcdef"});
503
+
504
+ testCM("bookmarkCursor", function(cm) {
505
+ var pos01 = cm.cursorCoords(Pos(0, 1)), pos11 = cm.cursorCoords(Pos(1, 1)),
506
+ pos20 = cm.cursorCoords(Pos(2, 0)), pos30 = cm.cursorCoords(Pos(3, 0)),
507
+ pos41 = cm.cursorCoords(Pos(4, 1));
508
+ cm.setBookmark(Pos(0, 1), {widget: document.createTextNode("←"), insertLeft: true});
509
+ cm.setBookmark(Pos(2, 0), {widget: document.createTextNode("←"), insertLeft: true});
510
+ cm.setBookmark(Pos(1, 1), {widget: document.createTextNode("→")});
511
+ cm.setBookmark(Pos(3, 0), {widget: document.createTextNode("→")});
512
+ var new01 = cm.cursorCoords(Pos(0, 1)), new11 = cm.cursorCoords(Pos(1, 1)),
513
+ new20 = cm.cursorCoords(Pos(2, 0)), new30 = cm.cursorCoords(Pos(3, 0));
514
+ is(new01.left == pos01.left && new01.top == pos01.top, "at left, middle of line");
515
+ is(new11.left > pos11.left && new11.top == pos11.top, "at right, middle of line");
516
+ is(new20.left == pos20.left && new20.top == pos20.top, "at left, empty line");
517
+ is(new30.left > pos30.left && new30.top == pos30.top, "at right, empty line");
518
+ cm.setBookmark(Pos(4, 0), {widget: document.createTextNode("→")});
519
+ is(cm.cursorCoords(Pos(4, 1)).left > pos41.left, "single-char bug");
520
+ }, {value: "foo\nbar\n\n\nx\ny"});
521
+
522
+ testCM("multiBookmarkCursor", function(cm) {
523
+ if (phantom) return;
524
+ var ms = [], m;
525
+ function add(insertLeft) {
526
+ for (var i = 0; i < 3; ++i) {
527
+ var node = document.createElement("span");
528
+ node.innerHTML = "X";
529
+ ms.push(cm.setBookmark(Pos(0, 1), {widget: node, insertLeft: insertLeft}));
530
+ }
531
+ }
532
+ var base1 = cm.cursorCoords(Pos(0, 1)).left, base4 = cm.cursorCoords(Pos(0, 4)).left;
533
+ add(true);
534
+ is(Math.abs(base1 - cm.cursorCoords(Pos(0, 1)).left) < .1);
535
+ while (m = ms.pop()) m.clear();
536
+ add(false);
537
+ is(Math.abs(base4 - cm.cursorCoords(Pos(0, 1)).left) < .1);
538
+ }, {value: "abcdefg"});
539
+
540
+ testCM("getAllMarks", function(cm) {
541
+ addDoc(cm, 10, 10);
542
+ var m1 = cm.setBookmark(Pos(0, 2));
543
+ var m2 = cm.markText(Pos(0, 2), Pos(3, 2));
544
+ var m3 = cm.markText(Pos(1, 2), Pos(1, 8));
545
+ var m4 = cm.markText(Pos(8, 0), Pos(9, 0));
546
+ eq(cm.getAllMarks().length, 4);
547
+ m1.clear();
548
+ m3.clear();
549
+ eq(cm.getAllMarks().length, 2);
550
+ });
551
+
552
+ testCM("bug577", function(cm) {
553
+ cm.setValue("a\nb");
554
+ cm.clearHistory();
555
+ cm.setValue("fooooo");
556
+ cm.undo();
557
+ });
558
+
559
+ testCM("scrollSnap", function(cm) {
560
+ cm.setSize(100, 100);
561
+ addDoc(cm, 200, 200);
562
+ cm.setCursor(Pos(100, 180));
563
+ var info = cm.getScrollInfo();
564
+ is(info.left > 0 && info.top > 0);
565
+ cm.setCursor(Pos(0, 0));
566
+ info = cm.getScrollInfo();
567
+ is(info.left == 0 && info.top == 0, "scrolled clean to top");
568
+ cm.setCursor(Pos(100, 180));
569
+ cm.setCursor(Pos(199, 0));
570
+ info = cm.getScrollInfo();
571
+ is(info.left == 0 && info.top + 2 > info.height - cm.getScrollerElement().clientHeight, "scrolled clean to bottom");
572
+ });
573
+
574
+ testCM("scrollIntoView", function(cm) {
575
+ if (phantom) return;
576
+ var outer = cm.getWrapperElement().getBoundingClientRect();
577
+ function test(line, ch) {
578
+ var pos = Pos(line, ch);
579
+ cm.scrollIntoView(pos);
580
+ var box = cm.charCoords(pos, "window");
581
+ is(box.left >= outer.left && box.right <= outer.right &&
582
+ box.top >= outer.top && box.bottom <= outer.bottom);
583
+ }
584
+ addDoc(cm, 200, 200);
585
+ test(199, 199);
586
+ test(0, 0);
587
+ test(100, 100);
588
+ test(199, 0);
589
+ test(0, 199);
590
+ test(100, 100);
591
+ });
592
+
593
+ testCM("selectionPos", function(cm) {
594
+ if (phantom) return;
595
+ cm.setSize(100, 100);
596
+ addDoc(cm, 200, 100);
597
+ cm.setSelection(Pos(1, 100), Pos(98, 100));
598
+ var lineWidth = cm.charCoords(Pos(0, 200), "local").left;
599
+ var lineHeight = (cm.charCoords(Pos(99)).top - cm.charCoords(Pos(0)).top) / 100;
600
+ cm.scrollTo(0, 0);
601
+ var selElt = byClassName(cm.getWrapperElement(), "CodeMirror-selected");
602
+ var outer = cm.getWrapperElement().getBoundingClientRect();
603
+ var sawMiddle, sawTop, sawBottom;
604
+ for (var i = 0, e = selElt.length; i < e; ++i) {
605
+ var box = selElt[i].getBoundingClientRect();
606
+ var atLeft = box.left - outer.left < 30;
607
+ var width = box.right - box.left;
608
+ var atRight = box.right - outer.left > .8 * lineWidth;
609
+ if (atLeft && atRight) {
610
+ sawMiddle = true;
611
+ is(box.bottom - box.top > 90 * lineHeight, "middle high");
612
+ is(width > .9 * lineWidth, "middle wide");
613
+ } else {
614
+ is(width > .4 * lineWidth, "top/bot wide enough");
615
+ is(width < .6 * lineWidth, "top/bot slim enough");
616
+ if (atLeft) {
617
+ sawBottom = true;
618
+ is(box.top - outer.top > 96 * lineHeight, "bot below");
619
+ } else if (atRight) {
620
+ sawTop = true;
621
+ is(box.top - outer.top < 2.1 * lineHeight, "top above");
622
+ }
623
+ }
624
+ }
625
+ is(sawTop && sawBottom && sawMiddle, "all parts");
626
+ }, null);
627
+
628
+ testCM("restoreHistory", function(cm) {
629
+ cm.setValue("abc\ndef");
630
+ cm.setLine(1, "hello");
631
+ cm.setLine(0, "goop");
632
+ cm.undo();
633
+ var storedVal = cm.getValue(), storedHist = cm.getHistory();
634
+ if (window.JSON) storedHist = JSON.parse(JSON.stringify(storedHist));
635
+ eq(storedVal, "abc\nhello");
636
+ cm.setValue("");
637
+ cm.clearHistory();
638
+ eq(cm.historySize().undo, 0);
639
+ cm.setValue(storedVal);
640
+ cm.setHistory(storedHist);
641
+ cm.redo();
642
+ eq(cm.getValue(), "goop\nhello");
643
+ cm.undo(); cm.undo();
644
+ eq(cm.getValue(), "abc\ndef");
645
+ });
646
+
647
+ testCM("doubleScrollbar", function(cm) {
648
+ var dummy = document.body.appendChild(document.createElement("p"));
649
+ dummy.style.cssText = "height: 50px; overflow: scroll; width: 50px";
650
+ var scrollbarWidth = dummy.offsetWidth + 1 - dummy.clientWidth;
651
+ document.body.removeChild(dummy);
652
+ if (scrollbarWidth < 2) return;
653
+ cm.setSize(null, 100);
654
+ addDoc(cm, 1, 300);
655
+ var wrap = cm.getWrapperElement();
656
+ is(wrap.offsetWidth - byClassName(wrap, "CodeMirror-lines")[0].offsetWidth <= scrollbarWidth * 1.5);
657
+ });
658
+
659
+ testCM("weirdLinebreaks", function(cm) {
660
+ cm.setValue("foo\nbar\rbaz\r\nquux\n\rplop");
661
+ is(cm.getValue(), "foo\nbar\nbaz\nquux\n\nplop");
662
+ is(cm.lineCount(), 6);
663
+ cm.setValue("\n\n");
664
+ is(cm.lineCount(), 3);
665
+ });
666
+
667
+ testCM("setSize", function(cm) {
668
+ cm.setSize(100, 100);
669
+ var wrap = cm.getWrapperElement();
670
+ is(wrap.offsetWidth, 100);
671
+ is(wrap.offsetHeight, 100);
672
+ cm.setSize("100%", "3em");
673
+ is(wrap.style.width, "100%");
674
+ is(wrap.style.height, "3em");
675
+ cm.setSize(null, 40);
676
+ is(wrap.style.width, "100%");
677
+ is(wrap.style.height, "40px");
678
+ });
679
+
680
+ function foldLines(cm, start, end, autoClear) {
681
+ return cm.markText(Pos(start, 0), Pos(end - 1), {
682
+ inclusiveLeft: true,
683
+ inclusiveRight: true,
684
+ collapsed: true,
685
+ clearOnEnter: autoClear
686
+ });
687
+ }
688
+
689
+ testCM("collapsedLines", function(cm) {
690
+ addDoc(cm, 4, 10);
691
+ var range = foldLines(cm, 4, 5), cleared = 0;
692
+ CodeMirror.on(range, "clear", function() {cleared++;});
693
+ cm.setCursor(Pos(3, 0));
694
+ CodeMirror.commands.goLineDown(cm);
695
+ eqPos(cm.getCursor(), Pos(5, 0));
696
+ cm.setLine(3, "abcdefg");
697
+ cm.setCursor(Pos(3, 6));
698
+ CodeMirror.commands.goLineDown(cm);
699
+ eqPos(cm.getCursor(), Pos(5, 4));
700
+ cm.setLine(3, "ab");
701
+ cm.setCursor(Pos(3, 2));
702
+ CodeMirror.commands.goLineDown(cm);
703
+ eqPos(cm.getCursor(), Pos(5, 2));
704
+ cm.operation(function() {range.clear(); range.clear();});
705
+ eq(cleared, 1);
706
+ });
707
+
708
+ testCM("collapsedRangeCoordsChar", function(cm) {
709
+ var pos_1_3 = cm.charCoords(Pos(1, 3));
710
+ pos_1_3.left += 2; pos_1_3.top += 2;
711
+ var opts = {collapsed: true, inclusiveLeft: true, inclusiveRight: true};
712
+ var m1 = cm.markText(Pos(0, 0), Pos(2, 0), opts);
713
+ eqPos(cm.coordsChar(pos_1_3), Pos(3, 3));
714
+ m1.clear();
715
+ var m1 = cm.markText(Pos(0, 0), Pos(1, 1), opts);
716
+ var m2 = cm.markText(Pos(1, 1), Pos(2, 0), opts);
717
+ eqPos(cm.coordsChar(pos_1_3), Pos(3, 3));
718
+ m1.clear(); m2.clear();
719
+ var m1 = cm.markText(Pos(0, 0), Pos(1, 6), opts);
720
+ eqPos(cm.coordsChar(pos_1_3), Pos(3, 3));
721
+ }, {value: "123456\nabcdef\nghijkl\nmnopqr\n"});
722
+
723
+ testCM("hiddenLinesAutoUnfold", function(cm) {
724
+ var range = foldLines(cm, 1, 3, true), cleared = 0;
725
+ CodeMirror.on(range, "clear", function() {cleared++;});
726
+ cm.setCursor(Pos(3, 0));
727
+ eq(cleared, 0);
728
+ cm.execCommand("goCharLeft");
729
+ eq(cleared, 1);
730
+ range = foldLines(cm, 1, 3, true);
731
+ CodeMirror.on(range, "clear", function() {cleared++;});
732
+ eqPos(cm.getCursor(), Pos(3, 0));
733
+ cm.setCursor(Pos(0, 3));
734
+ cm.execCommand("goCharRight");
735
+ eq(cleared, 2);
736
+ }, {value: "abc\ndef\nghi\njkl"});
737
+
738
+ testCM("hiddenLinesSelectAll", function(cm) { // Issue #484
739
+ addDoc(cm, 4, 20);
740
+ foldLines(cm, 0, 10);
741
+ foldLines(cm, 11, 20);
742
+ CodeMirror.commands.selectAll(cm);
743
+ eqPos(cm.getCursor(true), Pos(10, 0));
744
+ eqPos(cm.getCursor(false), Pos(10, 4));
745
+ });
746
+
747
+
748
+ testCM("everythingFolded", function(cm) {
749
+ addDoc(cm, 2, 2);
750
+ function enterPress() {
751
+ cm.triggerOnKeyDown({type: "keydown", keyCode: 13, preventDefault: function(){}, stopPropagation: function(){}});
752
+ }
753
+ var fold = foldLines(cm, 0, 2);
754
+ enterPress();
755
+ eq(cm.getValue(), "xx\nxx");
756
+ fold.clear();
757
+ fold = foldLines(cm, 0, 2, true);
758
+ eq(fold.find(), null);
759
+ enterPress();
760
+ eq(cm.getValue(), "\nxx\nxx");
761
+ });
762
+
763
+ testCM("structuredFold", function(cm) {
764
+ if (phantom) return;
765
+ addDoc(cm, 4, 8);
766
+ var range = cm.markText(Pos(1, 2), Pos(6, 2), {
767
+ replacedWith: document.createTextNode("Q")
768
+ });
769
+ cm.setCursor(0, 3);
770
+ CodeMirror.commands.goLineDown(cm);
771
+ eqPos(cm.getCursor(), Pos(6, 2));
772
+ CodeMirror.commands.goCharLeft(cm);
773
+ eqPos(cm.getCursor(), Pos(1, 2));
774
+ CodeMirror.commands.delCharAfter(cm);
775
+ eq(cm.getValue(), "xxxx\nxxxx\nxxxx");
776
+ addDoc(cm, 4, 8);
777
+ range = cm.markText(Pos(1, 2), Pos(6, 2), {
778
+ replacedWith: document.createTextNode("M"),
779
+ clearOnEnter: true
780
+ });
781
+ var cleared = 0;
782
+ CodeMirror.on(range, "clear", function(){++cleared;});
783
+ cm.setCursor(0, 3);
784
+ CodeMirror.commands.goLineDown(cm);
785
+ eqPos(cm.getCursor(), Pos(6, 2));
786
+ CodeMirror.commands.goCharLeft(cm);
787
+ eqPos(cm.getCursor(), Pos(6, 1));
788
+ eq(cleared, 1);
789
+ range.clear();
790
+ eq(cleared, 1);
791
+ range = cm.markText(Pos(1, 2), Pos(6, 2), {
792
+ replacedWith: document.createTextNode("Q"),
793
+ clearOnEnter: true
794
+ });
795
+ range.clear();
796
+ cm.setCursor(1, 2);
797
+ CodeMirror.commands.goCharRight(cm);
798
+ eqPos(cm.getCursor(), Pos(1, 3));
799
+ range = cm.markText(Pos(2, 0), Pos(4, 4), {
800
+ replacedWith: document.createTextNode("M")
801
+ });
802
+ cm.setCursor(1, 0);
803
+ CodeMirror.commands.goLineDown(cm);
804
+ eqPos(cm.getCursor(), Pos(2, 0));
805
+ }, null);
806
+
807
+ testCM("nestedFold", function(cm) {
808
+ addDoc(cm, 10, 3);
809
+ function fold(ll, cl, lr, cr) {
810
+ return cm.markText(Pos(ll, cl), Pos(lr, cr), {collapsed: true});
811
+ }
812
+ var inner1 = fold(0, 6, 1, 3), inner2 = fold(0, 2, 1, 8), outer = fold(0, 1, 2, 3), inner0 = fold(0, 5, 0, 6);
813
+ cm.setCursor(0, 1);
814
+ CodeMirror.commands.goCharRight(cm);
815
+ eqPos(cm.getCursor(), Pos(2, 3));
816
+ inner0.clear();
817
+ CodeMirror.commands.goCharLeft(cm);
818
+ eqPos(cm.getCursor(), Pos(0, 1));
819
+ outer.clear();
820
+ CodeMirror.commands.goCharRight(cm);
821
+ eqPos(cm.getCursor(), Pos(0, 2));
822
+ CodeMirror.commands.goCharRight(cm);
823
+ eqPos(cm.getCursor(), Pos(1, 8));
824
+ inner2.clear();
825
+ CodeMirror.commands.goCharLeft(cm);
826
+ eqPos(cm.getCursor(), Pos(1, 7));
827
+ cm.setCursor(0, 5);
828
+ CodeMirror.commands.goCharRight(cm);
829
+ eqPos(cm.getCursor(), Pos(0, 6));
830
+ CodeMirror.commands.goCharRight(cm);
831
+ eqPos(cm.getCursor(), Pos(1, 3));
832
+ });
833
+
834
+ testCM("badNestedFold", function(cm) {
835
+ addDoc(cm, 4, 4);
836
+ cm.markText(Pos(0, 2), Pos(3, 2), {collapsed: true});
837
+ var caught;
838
+ try {cm.markText(Pos(0, 1), Pos(0, 3), {collapsed: true});}
839
+ catch(e) {caught = e;}
840
+ is(caught instanceof Error, "no error");
841
+ is(/overlap/i.test(caught.message), "wrong error");
842
+ });
843
+
844
+ testCM("wrappingInlineWidget", function(cm) {
845
+ cm.setSize("11em");
846
+ var w = document.createElement("span");
847
+ w.style.color = "red";
848
+ w.innerHTML = "one two three four";
849
+ cm.markText(Pos(0, 6), Pos(0, 9), {replacedWith: w});
850
+ var cur0 = cm.cursorCoords(Pos(0, 0)), cur1 = cm.cursorCoords(Pos(0, 10));
851
+ is(cur0.top < cur1.top);
852
+ is(cur0.bottom < cur1.bottom);
853
+ var curL = cm.cursorCoords(Pos(0, 6)), curR = cm.cursorCoords(Pos(0, 9));
854
+ eq(curL.top, cur0.top);
855
+ eq(curL.bottom, cur0.bottom);
856
+ eq(curR.top, cur1.top);
857
+ eq(curR.bottom, cur1.bottom);
858
+ cm.replaceRange("", Pos(0, 9), Pos(0));
859
+ curR = cm.cursorCoords(Pos(0, 9));
860
+ eq(curR.top, cur1.top);
861
+ eq(curR.bottom, cur1.bottom);
862
+ }, {value: "1 2 3 xxx 4", lineWrapping: true});
863
+
864
+ testCM("changedInlineWidget", function(cm) {
865
+ cm.setSize("10em");
866
+ var w = document.createElement("span");
867
+ w.innerHTML = "x";
868
+ var m = cm.markText(Pos(0, 4), Pos(0, 5), {replacedWith: w});
869
+ w.innerHTML = "and now the widget is really really long all of a sudden and a scrollbar is needed";
870
+ m.changed();
871
+ var hScroll = byClassName(cm.getWrapperElement(), "CodeMirror-hscrollbar")[0];
872
+ is(hScroll.scrollWidth > hScroll.clientWidth);
873
+ }, {value: "hello there"});
874
+
875
+ testCM("changedBookmark", function(cm) {
876
+ cm.setSize("10em");
877
+ var w = document.createElement("span");
878
+ w.innerHTML = "x";
879
+ var m = cm.setBookmark(Pos(0, 4), {widget: w});
880
+ w.innerHTML = "and now the widget is really really long all of a sudden and a scrollbar is needed";
881
+ m.changed();
882
+ var hScroll = byClassName(cm.getWrapperElement(), "CodeMirror-hscrollbar")[0];
883
+ is(hScroll.scrollWidth > hScroll.clientWidth);
884
+ }, {value: "abcdefg"});
885
+
886
+ testCM("inlineWidget", function(cm) {
887
+ var w = cm.setBookmark(Pos(0, 2), {widget: document.createTextNode("uu")});
888
+ cm.setCursor(0, 2);
889
+ CodeMirror.commands.goLineDown(cm);
890
+ eqPos(cm.getCursor(), Pos(1, 4));
891
+ cm.setCursor(0, 2);
892
+ cm.replaceSelection("hi");
893
+ eqPos(w.find(), Pos(0, 2));
894
+ cm.setCursor(0, 1);
895
+ cm.replaceSelection("ay");
896
+ eqPos(w.find(), Pos(0, 4));
897
+ eq(cm.getLine(0), "uayuhiuu");
898
+ }, {value: "uuuu\nuuuuuu"});
899
+
900
+ testCM("wrappingAndResizing", function(cm) {
901
+ cm.setSize(null, "auto");
902
+ cm.setOption("lineWrapping", true);
903
+ var wrap = cm.getWrapperElement(), h0 = wrap.offsetHeight;
904
+ var doc = "xxx xxx xxx xxx xxx";
905
+ cm.setValue(doc);
906
+ for (var step = 10, w = cm.charCoords(Pos(0, 18), "div").right;; w += step) {
907
+ cm.setSize(w);
908
+ if (wrap.offsetHeight <= h0 * (opera_lt10 ? 1.2 : 1.5)) {
909
+ if (step == 10) { w -= 10; step = 1; }
910
+ else break;
911
+ }
912
+ }
913
+ // Ensure that putting the cursor at the end of the maximally long
914
+ // line doesn't cause wrapping to happen.
915
+ cm.setCursor(Pos(0, doc.length));
916
+ eq(wrap.offsetHeight, h0);
917
+ cm.replaceSelection("x");
918
+ is(wrap.offsetHeight > h0, "wrapping happens");
919
+ // Now add a max-height and, in a document consisting of
920
+ // almost-wrapped lines, go over it so that a scrollbar appears.
921
+ cm.setValue(doc + "\n" + doc + "\n");
922
+ cm.getScrollerElement().style.maxHeight = "100px";
923
+ cm.replaceRange("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n!\n", Pos(2, 0));
924
+ forEach([Pos(0, doc.length), Pos(0, doc.length - 1),
925
+ Pos(0, 0), Pos(1, doc.length), Pos(1, doc.length - 1)],
926
+ function(pos) {
927
+ var coords = cm.charCoords(pos);
928
+ eqPos(pos, cm.coordsChar({left: coords.left + 2, top: coords.top + 5}));
929
+ });
930
+ }, null, ie_lt8);
931
+
932
+ testCM("measureEndOfLine", function(cm) {
933
+ cm.setSize(null, "auto");
934
+ var inner = byClassName(cm.getWrapperElement(), "CodeMirror-lines")[0].firstChild;
935
+ var lh = inner.offsetHeight;
936
+ for (var step = 10, w = cm.charCoords(Pos(0, 7), "div").right;; w += step) {
937
+ cm.setSize(w);
938
+ if (inner.offsetHeight < 2.5 * lh) {
939
+ if (step == 10) { w -= 10; step = 1; }
940
+ else break;
941
+ }
942
+ }
943
+ cm.setValue(cm.getValue() + "\n\n");
944
+ var endPos = cm.charCoords(Pos(0, 18), "local");
945
+ is(endPos.top > lh * .8, "not at top");
946
+ is(endPos.left > w - 20, "not at right");
947
+ endPos = cm.charCoords(Pos(0, 18));
948
+ eqPos(cm.coordsChar({left: endPos.left, top: endPos.top + 5}), Pos(0, 18));
949
+ }, {mode: "text/html", value: "<!-- foo barrr -->", lineWrapping: true}, ie_lt8 || opera_lt10);
950
+
951
+ testCM("scrollVerticallyAndHorizontally", function(cm) {
952
+ cm.setSize(100, 100);
953
+ addDoc(cm, 40, 40);
954
+ cm.setCursor(39);
955
+ var wrap = cm.getWrapperElement(), bar = byClassName(wrap, "CodeMirror-vscrollbar")[0];
956
+ is(bar.offsetHeight < wrap.offsetHeight, "vertical scrollbar limited by horizontal one");
957
+ var cursorBox = byClassName(wrap, "CodeMirror-cursor")[0].getBoundingClientRect();
958
+ var editorBox = wrap.getBoundingClientRect();
959
+ is(cursorBox.bottom < editorBox.top + cm.getScrollerElement().clientHeight,
960
+ "bottom line visible");
961
+ }, {lineNumbers: true});
962
+
963
+ testCM("moveVstuck", function(cm) {
964
+ var lines = byClassName(cm.getWrapperElement(), "CodeMirror-lines")[0].firstChild, h0 = lines.offsetHeight;
965
+ var val = "fooooooooooooooooooooooooo baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaar\n";
966
+ cm.setValue(val);
967
+ for (var w = cm.charCoords(Pos(0, 26), "div").right * 2.8;; w += 5) {
968
+ cm.setSize(w);
969
+ if (lines.offsetHeight <= 3.5 * h0) break;
970
+ }
971
+ cm.setCursor(Pos(0, val.length - 1));
972
+ cm.moveV(-1, "line");
973
+ eqPos(cm.getCursor(), Pos(0, 26));
974
+ }, {lineWrapping: true}, ie_lt8 || opera_lt10);
975
+
976
+ testCM("clickTab", function(cm) {
977
+ var p0 = cm.charCoords(Pos(0, 0));
978
+ eqPos(cm.coordsChar({left: p0.left + 5, top: p0.top + 5}), Pos(0, 0));
979
+ eqPos(cm.coordsChar({left: p0.right - 5, top: p0.top + 5}), Pos(0, 1));
980
+ }, {value: "\t\n\n", lineWrapping: true, tabSize: 8});
981
+
982
+ testCM("verticalScroll", function(cm) {
983
+ cm.setSize(100, 200);
984
+ cm.setValue("foo\nbar\nbaz\n");
985
+ var sc = cm.getScrollerElement(), baseWidth = sc.scrollWidth;
986
+ cm.setLine(0, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaah");
987
+ is(sc.scrollWidth > baseWidth, "scrollbar present");
988
+ cm.setLine(0, "foo");
989
+ if (!phantom) eq(sc.scrollWidth, baseWidth, "scrollbar gone");
990
+ cm.setLine(0, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaah");
991
+ cm.setLine(1, "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbh");
992
+ is(sc.scrollWidth > baseWidth, "present again");
993
+ var curWidth = sc.scrollWidth;
994
+ cm.setLine(0, "foo");
995
+ is(sc.scrollWidth < curWidth, "scrollbar smaller");
996
+ is(sc.scrollWidth > baseWidth, "but still present");
997
+ });
998
+
999
+ testCM("extraKeys", function(cm) {
1000
+ var outcome;
1001
+ function fakeKey(expected, code, props) {
1002
+ if (typeof code == "string") code = code.charCodeAt(0);
1003
+ var e = {type: "keydown", keyCode: code, preventDefault: function(){}, stopPropagation: function(){}};
1004
+ if (props) for (var n in props) e[n] = props[n];
1005
+ outcome = null;
1006
+ cm.triggerOnKeyDown(e);
1007
+ eq(outcome, expected);
1008
+ }
1009
+ CodeMirror.commands.testCommand = function() {outcome = "tc";};
1010
+ CodeMirror.commands.goTestCommand = function() {outcome = "gtc";};
1011
+ cm.setOption("extraKeys", {"Shift-X": function() {outcome = "sx";},
1012
+ "X": function() {outcome = "x";},
1013
+ "Ctrl-Alt-U": function() {outcome = "cau";},
1014
+ "End": "testCommand",
1015
+ "Home": "goTestCommand",
1016
+ "Tab": false});
1017
+ fakeKey(null, "U");
1018
+ fakeKey("cau", "U", {ctrlKey: true, altKey: true});
1019
+ fakeKey(null, "U", {shiftKey: true, ctrlKey: true, altKey: true});
1020
+ fakeKey("x", "X");
1021
+ fakeKey("sx", "X", {shiftKey: true});
1022
+ fakeKey("tc", 35);
1023
+ fakeKey(null, 35, {shiftKey: true});
1024
+ fakeKey("gtc", 36);
1025
+ fakeKey("gtc", 36, {shiftKey: true});
1026
+ fakeKey(null, 9);
1027
+ }, null, window.opera && mac);
1028
+
1029
+ testCM("wordMovementCommands", function(cm) {
1030
+ cm.execCommand("goWordLeft");
1031
+ eqPos(cm.getCursor(), Pos(0, 0));
1032
+ cm.execCommand("goWordRight"); cm.execCommand("goWordRight");
1033
+ eqPos(cm.getCursor(), Pos(0, 7));
1034
+ cm.execCommand("goWordLeft");
1035
+ eqPos(cm.getCursor(), Pos(0, 5));
1036
+ cm.execCommand("goWordRight"); cm.execCommand("goWordRight");
1037
+ eqPos(cm.getCursor(), Pos(0, 12));
1038
+ cm.execCommand("goWordLeft");
1039
+ eqPos(cm.getCursor(), Pos(0, 9));
1040
+ cm.execCommand("goWordRight"); cm.execCommand("goWordRight"); cm.execCommand("goWordRight");
1041
+ eqPos(cm.getCursor(), Pos(0, 24));
1042
+ cm.execCommand("goWordRight"); cm.execCommand("goWordRight");
1043
+ eqPos(cm.getCursor(), Pos(1, 9));
1044
+ cm.execCommand("goWordRight");
1045
+ eqPos(cm.getCursor(), Pos(1, 13));
1046
+ cm.execCommand("goWordRight"); cm.execCommand("goWordRight");
1047
+ eqPos(cm.getCursor(), Pos(2, 0));
1048
+ }, {value: "this is (the) firstline.\na foo12\u00e9\u00f8\u00d7bar\n"});
1049
+
1050
+ testCM("groupMovementCommands", function(cm) {
1051
+ cm.execCommand("goGroupLeft");
1052
+ eqPos(cm.getCursor(), Pos(0, 0));
1053
+ cm.execCommand("goGroupRight");
1054
+ eqPos(cm.getCursor(), Pos(0, 4));
1055
+ cm.execCommand("goGroupRight");
1056
+ eqPos(cm.getCursor(), Pos(0, 7));
1057
+ cm.execCommand("goGroupRight");
1058
+ eqPos(cm.getCursor(), Pos(0, 10));
1059
+ cm.execCommand("goGroupLeft");
1060
+ eqPos(cm.getCursor(), Pos(0, 7));
1061
+ cm.execCommand("goGroupRight"); cm.execCommand("goGroupRight"); cm.execCommand("goGroupRight");
1062
+ eqPos(cm.getCursor(), Pos(0, 15));
1063
+ cm.setCursor(Pos(0, 17));
1064
+ cm.execCommand("goGroupLeft");
1065
+ eqPos(cm.getCursor(), Pos(0, 16));
1066
+ cm.execCommand("goGroupLeft");
1067
+ eqPos(cm.getCursor(), Pos(0, 14));
1068
+ cm.execCommand("goGroupRight"); cm.execCommand("goGroupRight");
1069
+ eqPos(cm.getCursor(), Pos(0, 20));
1070
+ cm.execCommand("goGroupRight");
1071
+ eqPos(cm.getCursor(), Pos(1, 5));
1072
+ cm.execCommand("goGroupLeft"); cm.execCommand("goGroupLeft");
1073
+ eqPos(cm.getCursor(), Pos(1, 0));
1074
+ cm.execCommand("goGroupLeft");
1075
+ eqPos(cm.getCursor(), Pos(0, 16));
1076
+ }, {value: "booo ba---quux. ffff\n abc d"});
1077
+
1078
+ testCM("charMovementCommands", function(cm) {
1079
+ cm.execCommand("goCharLeft"); cm.execCommand("goColumnLeft");
1080
+ eqPos(cm.getCursor(), Pos(0, 0));
1081
+ cm.execCommand("goCharRight"); cm.execCommand("goCharRight");
1082
+ eqPos(cm.getCursor(), Pos(0, 2));
1083
+ cm.setCursor(Pos(1, 0));
1084
+ cm.execCommand("goColumnLeft");
1085
+ eqPos(cm.getCursor(), Pos(1, 0));
1086
+ cm.execCommand("goCharLeft");
1087
+ eqPos(cm.getCursor(), Pos(0, 5));
1088
+ cm.execCommand("goColumnRight");
1089
+ eqPos(cm.getCursor(), Pos(0, 5));
1090
+ cm.execCommand("goCharRight");
1091
+ eqPos(cm.getCursor(), Pos(1, 0));
1092
+ cm.execCommand("goLineEnd");
1093
+ eqPos(cm.getCursor(), Pos(1, 5));
1094
+ cm.execCommand("goLineStartSmart");
1095
+ eqPos(cm.getCursor(), Pos(1, 1));
1096
+ cm.execCommand("goLineStartSmart");
1097
+ eqPos(cm.getCursor(), Pos(1, 0));
1098
+ cm.setCursor(Pos(2, 0));
1099
+ cm.execCommand("goCharRight"); cm.execCommand("goColumnRight");
1100
+ eqPos(cm.getCursor(), Pos(2, 0));
1101
+ }, {value: "line1\n ine2\n"});
1102
+
1103
+ testCM("verticalMovementCommands", function(cm) {
1104
+ cm.execCommand("goLineUp");
1105
+ eqPos(cm.getCursor(), Pos(0, 0));
1106
+ cm.execCommand("goLineDown");
1107
+ if (!phantom) // This fails in PhantomJS, though not in a real Webkit
1108
+ eqPos(cm.getCursor(), Pos(1, 0));
1109
+ cm.setCursor(Pos(1, 12));
1110
+ cm.execCommand("goLineDown");
1111
+ eqPos(cm.getCursor(), Pos(2, 5));
1112
+ cm.execCommand("goLineDown");
1113
+ eqPos(cm.getCursor(), Pos(3, 0));
1114
+ cm.execCommand("goLineUp");
1115
+ eqPos(cm.getCursor(), Pos(2, 5));
1116
+ cm.execCommand("goLineUp");
1117
+ eqPos(cm.getCursor(), Pos(1, 12));
1118
+ cm.execCommand("goPageDown");
1119
+ eqPos(cm.getCursor(), Pos(5, 0));
1120
+ cm.execCommand("goPageDown"); cm.execCommand("goLineDown");
1121
+ eqPos(cm.getCursor(), Pos(5, 0));
1122
+ cm.execCommand("goPageUp");
1123
+ eqPos(cm.getCursor(), Pos(0, 0));
1124
+ }, {value: "line1\nlong long line2\nline3\n\nline5\n"});
1125
+
1126
+ testCM("verticalMovementCommandsWrapping", function(cm) {
1127
+ cm.setSize(120);
1128
+ cm.setCursor(Pos(0, 5));
1129
+ cm.execCommand("goLineDown");
1130
+ eq(cm.getCursor().line, 0);
1131
+ is(cm.getCursor().ch > 5, "moved beyond wrap");
1132
+ for (var i = 0; ; ++i) {
1133
+ is(i < 20, "no endless loop");
1134
+ cm.execCommand("goLineDown");
1135
+ var cur = cm.getCursor();
1136
+ if (cur.line == 1) eq(cur.ch, 5);
1137
+ if (cur.line == 2) { eq(cur.ch, 1); break; }
1138
+ }
1139
+ }, {value: "a very long line that wraps around somehow so that we can test cursor movement\nshortone\nk",
1140
+ lineWrapping: true});
1141
+
1142
+ testCM("rtlMovement", function(cm) {
1143
+ forEach(["خحج", "خحabcخحج", "abخحخحجcd", "abخde", "abخح2342خ1حج", "خ1ح2خح3حxج",
1144
+ "خحcd", "1خحcd", "abcdeح1ج", "خمرحبها مها!", "foobarر",
1145
+ "<img src=\"/בדיקה3.jpg\">"], function(line) {
1146
+ var inv = line.charAt(0) == "خ";
1147
+ cm.setValue(line + "\n"); cm.execCommand(inv ? "goLineEnd" : "goLineStart");
1148
+ var cursor = byClassName(cm.getWrapperElement(), "CodeMirror-cursor")[0];
1149
+ var prevX = cursor.offsetLeft, prevY = cursor.offsetTop;
1150
+ for (var i = 0; i <= line.length; ++i) {
1151
+ cm.execCommand("goCharRight");
1152
+ if (i == line.length) is(cursor.offsetTop > prevY, "next line");
1153
+ else is(cursor.offsetLeft > prevX, "moved right");
1154
+ prevX = cursor.offsetLeft; prevY = cursor.offsetTop;
1155
+ }
1156
+ cm.setCursor(0, 0); cm.execCommand(inv ? "goLineStart" : "goLineEnd");
1157
+ prevX = cursor.offsetLeft;
1158
+ for (var i = 0; i < line.length; ++i) {
1159
+ cm.execCommand("goCharLeft");
1160
+ is(cursor.offsetLeft < prevX, "moved left");
1161
+ prevX = cursor.offsetLeft;
1162
+ }
1163
+ });
1164
+ });
1165
+
1166
+ // Verify that updating a line clears its bidi ordering
1167
+ testCM("bidiUpdate", function(cm) {
1168
+ cm.setCursor(Pos(0, 2));
1169
+ cm.replaceSelection("خحج", "start");
1170
+ cm.execCommand("goCharRight");
1171
+ eqPos(cm.getCursor(), Pos(0, 4));
1172
+ }, {value: "abcd\n"});
1173
+
1174
+ testCM("movebyTextUnit", function(cm) {
1175
+ cm.setValue("בְּרֵאשִ\ńéée\n");
1176
+ cm.execCommand("goLineEnd");
1177
+ for (var i = 0; i < 4; ++i) cm.execCommand("goCharRight");
1178
+ eqPos(cm.getCursor(), Pos(0, 0));
1179
+ cm.execCommand("goCharRight");
1180
+ eqPos(cm.getCursor(), Pos(1, 0));
1181
+ cm.execCommand("goCharRight");
1182
+ cm.execCommand("goCharRight");
1183
+ eqPos(cm.getCursor(), Pos(1, 3));
1184
+ cm.execCommand("goCharRight");
1185
+ cm.execCommand("goCharRight");
1186
+ eqPos(cm.getCursor(), Pos(1, 6));
1187
+ });
1188
+
1189
+ testCM("lineChangeEvents", function(cm) {
1190
+ addDoc(cm, 3, 5);
1191
+ var log = [], want = ["ch 0", "ch 1", "del 2", "ch 0", "ch 0", "del 1", "del 3", "del 4"];
1192
+ for (var i = 0; i < 5; ++i) {
1193
+ CodeMirror.on(cm.getLineHandle(i), "delete", function(i) {
1194
+ return function() {log.push("del " + i);};
1195
+ }(i));
1196
+ CodeMirror.on(cm.getLineHandle(i), "change", function(i) {
1197
+ return function() {log.push("ch " + i);};
1198
+ }(i));
1199
+ }
1200
+ cm.replaceRange("x", Pos(0, 1));
1201
+ cm.replaceRange("xy", Pos(1, 1), Pos(2));
1202
+ cm.replaceRange("foo\nbar", Pos(0, 1));
1203
+ cm.replaceRange("", Pos(0, 0), Pos(cm.lineCount()));
1204
+ eq(log.length, want.length, "same length");
1205
+ for (var i = 0; i < log.length; ++i)
1206
+ eq(log[i], want[i]);
1207
+ });
1208
+
1209
+ testCM("scrollEntirelyToRight", function(cm) {
1210
+ if (phantom) return;
1211
+ addDoc(cm, 500, 2);
1212
+ cm.setCursor(Pos(0, 500));
1213
+ var wrap = cm.getWrapperElement(), cur = byClassName(wrap, "CodeMirror-cursor")[0];
1214
+ is(wrap.getBoundingClientRect().right > cur.getBoundingClientRect().left);
1215
+ });
1216
+
1217
+ testCM("lineWidgets", function(cm) {
1218
+ addDoc(cm, 500, 3);
1219
+ var last = cm.charCoords(Pos(2, 0));
1220
+ var node = document.createElement("div");
1221
+ node.innerHTML = "hi";
1222
+ var widget = cm.addLineWidget(1, node);
1223
+ is(last.top < cm.charCoords(Pos(2, 0)).top, "took up space");
1224
+ cm.setCursor(Pos(1, 1));
1225
+ cm.execCommand("goLineDown");
1226
+ eqPos(cm.getCursor(), Pos(2, 1));
1227
+ cm.execCommand("goLineUp");
1228
+ eqPos(cm.getCursor(), Pos(1, 1));
1229
+ });
1230
+
1231
+ testCM("lineWidgetFocus", function(cm) {
1232
+ var place = document.getElementById("testground");
1233
+ place.className = "offscreen";
1234
+ try {
1235
+ addDoc(cm, 500, 10);
1236
+ var node = document.createElement("input");
1237
+ var widget = cm.addLineWidget(1, node);
1238
+ node.focus();
1239
+ eq(document.activeElement, node);
1240
+ cm.replaceRange("new stuff", Pos(1, 0));
1241
+ eq(document.activeElement, node);
1242
+ } finally {
1243
+ place.className = "";
1244
+ }
1245
+ });
1246
+
1247
+ testCM("getLineNumber", function(cm) {
1248
+ addDoc(cm, 2, 20);
1249
+ var h1 = cm.getLineHandle(1);
1250
+ eq(cm.getLineNumber(h1), 1);
1251
+ cm.replaceRange("hi\nbye\n", Pos(0, 0));
1252
+ eq(cm.getLineNumber(h1), 3);
1253
+ cm.setValue("");
1254
+ eq(cm.getLineNumber(h1), null);
1255
+ });
1256
+
1257
+ testCM("jumpTheGap", function(cm) {
1258
+ var longLine = "abcdef ghiklmnop qrstuvw xyz ";
1259
+ longLine += longLine; longLine += longLine; longLine += longLine;
1260
+ cm.setLine(2, longLine);
1261
+ cm.setSize("200px", null);
1262
+ cm.getWrapperElement().style.lineHeight = 2;
1263
+ cm.refresh();
1264
+ cm.setCursor(Pos(0, 1));
1265
+ cm.execCommand("goLineDown");
1266
+ eqPos(cm.getCursor(), Pos(1, 1));
1267
+ cm.execCommand("goLineDown");
1268
+ eqPos(cm.getCursor(), Pos(2, 1));
1269
+ cm.execCommand("goLineDown");
1270
+ eq(cm.getCursor().line, 2);
1271
+ is(cm.getCursor().ch > 1);
1272
+ cm.execCommand("goLineUp");
1273
+ eqPos(cm.getCursor(), Pos(2, 1));
1274
+ cm.execCommand("goLineUp");
1275
+ eqPos(cm.getCursor(), Pos(1, 1));
1276
+ var node = document.createElement("div");
1277
+ node.innerHTML = "hi"; node.style.height = "30px";
1278
+ cm.addLineWidget(0, node);
1279
+ cm.addLineWidget(1, node.cloneNode(true), {above: true});
1280
+ cm.setCursor(Pos(0, 2));
1281
+ cm.execCommand("goLineDown");
1282
+ eqPos(cm.getCursor(), Pos(1, 2));
1283
+ cm.execCommand("goLineUp");
1284
+ eqPos(cm.getCursor(), Pos(0, 2));
1285
+ }, {lineWrapping: true, value: "abc\ndef\nghi\njkl\n"});
1286
+
1287
+ testCM("addLineClass", function(cm) {
1288
+ function cls(line, text, bg, wrap) {
1289
+ var i = cm.lineInfo(line);
1290
+ eq(i.textClass, text);
1291
+ eq(i.bgClass, bg);
1292
+ eq(i.wrapClass, wrap);
1293
+ }
1294
+ cm.addLineClass(0, "text", "foo");
1295
+ cm.addLineClass(0, "text", "bar");
1296
+ cm.addLineClass(1, "background", "baz");
1297
+ cm.addLineClass(1, "wrap", "foo");
1298
+ cls(0, "foo bar", null, null);
1299
+ cls(1, null, "baz", "foo");
1300
+ var lines = cm.display.lineDiv;
1301
+ eq(byClassName(lines, "foo").length, 2);
1302
+ eq(byClassName(lines, "bar").length, 1);
1303
+ eq(byClassName(lines, "baz").length, 1);
1304
+ cm.removeLineClass(0, "text", "foo");
1305
+ cls(0, "bar", null, null);
1306
+ cm.removeLineClass(0, "text", "foo");
1307
+ cls(0, "bar", null, null);
1308
+ cm.removeLineClass(0, "text", "bar");
1309
+ cls(0, null, null, null);
1310
+ cm.addLineClass(1, "wrap", "quux");
1311
+ cls(1, null, "baz", "foo quux");
1312
+ cm.removeLineClass(1, "wrap");
1313
+ cls(1, null, "baz", null);
1314
+ }, {value: "hohoho\n"});
1315
+
1316
+ testCM("atomicMarker", function(cm) {
1317
+ addDoc(cm, 10, 10);
1318
+ function atom(ll, cl, lr, cr, li, ri) {
1319
+ return cm.markText(Pos(ll, cl), Pos(lr, cr),
1320
+ {atomic: true, inclusiveLeft: li, inclusiveRight: ri});
1321
+ }
1322
+ var m = atom(0, 1, 0, 5);
1323
+ cm.setCursor(Pos(0, 1));
1324
+ cm.execCommand("goCharRight");
1325
+ eqPos(cm.getCursor(), Pos(0, 5));
1326
+ cm.execCommand("goCharLeft");
1327
+ eqPos(cm.getCursor(), Pos(0, 1));
1328
+ m.clear();
1329
+ m = atom(0, 0, 0, 5, true);
1330
+ eqPos(cm.getCursor(), Pos(0, 5), "pushed out");
1331
+ cm.execCommand("goCharLeft");
1332
+ eqPos(cm.getCursor(), Pos(0, 5));
1333
+ m.clear();
1334
+ m = atom(8, 4, 9, 10, false, true);
1335
+ cm.setCursor(Pos(9, 8));
1336
+ eqPos(cm.getCursor(), Pos(8, 4), "set");
1337
+ cm.execCommand("goCharRight");
1338
+ eqPos(cm.getCursor(), Pos(8, 4), "char right");
1339
+ cm.execCommand("goLineDown");
1340
+ eqPos(cm.getCursor(), Pos(8, 4), "line down");
1341
+ cm.execCommand("goCharLeft");
1342
+ eqPos(cm.getCursor(), Pos(8, 3));
1343
+ m.clear();
1344
+ m = atom(1, 1, 3, 8);
1345
+ cm.setCursor(Pos(0, 0));
1346
+ cm.setCursor(Pos(2, 0));
1347
+ eqPos(cm.getCursor(), Pos(3, 8));
1348
+ cm.execCommand("goCharLeft");
1349
+ eqPos(cm.getCursor(), Pos(1, 1));
1350
+ cm.execCommand("goCharRight");
1351
+ eqPos(cm.getCursor(), Pos(3, 8));
1352
+ cm.execCommand("goLineUp");
1353
+ eqPos(cm.getCursor(), Pos(1, 1));
1354
+ cm.execCommand("goLineDown");
1355
+ eqPos(cm.getCursor(), Pos(3, 8));
1356
+ cm.execCommand("delCharBefore");
1357
+ eq(cm.getValue().length, 80, "del chunk");
1358
+ m = atom(3, 0, 5, 5);
1359
+ cm.setCursor(Pos(3, 0));
1360
+ cm.execCommand("delWordAfter");
1361
+ eq(cm.getValue().length, 53, "del chunk");
1362
+ });
1363
+
1364
+ testCM("readOnlyMarker", function(cm) {
1365
+ function mark(ll, cl, lr, cr, at) {
1366
+ return cm.markText(Pos(ll, cl), Pos(lr, cr),
1367
+ {readOnly: true, atomic: at});
1368
+ }
1369
+ var m = mark(0, 1, 0, 4);
1370
+ cm.setCursor(Pos(0, 2));
1371
+ cm.replaceSelection("hi", "end");
1372
+ eqPos(cm.getCursor(), Pos(0, 2));
1373
+ eq(cm.getLine(0), "abcde");
1374
+ cm.execCommand("selectAll");
1375
+ cm.replaceSelection("oops");
1376
+ eq(cm.getValue(), "oopsbcd");
1377
+ cm.undo();
1378
+ eqPos(m.find().from, Pos(0, 1));
1379
+ eqPos(m.find().to, Pos(0, 4));
1380
+ m.clear();
1381
+ cm.setCursor(Pos(0, 2));
1382
+ cm.replaceSelection("hi");
1383
+ eq(cm.getLine(0), "abhicde");
1384
+ eqPos(cm.getCursor(), Pos(0, 4));
1385
+ m = mark(0, 2, 2, 2, true);
1386
+ cm.setSelection(Pos(1, 1), Pos(2, 4));
1387
+ cm.replaceSelection("t", "end");
1388
+ eqPos(cm.getCursor(), Pos(2, 3));
1389
+ eq(cm.getLine(2), "klto");
1390
+ cm.execCommand("goCharLeft");
1391
+ cm.execCommand("goCharLeft");
1392
+ eqPos(cm.getCursor(), Pos(0, 2));
1393
+ cm.setSelection(Pos(0, 1), Pos(0, 3));
1394
+ cm.replaceSelection("xx");
1395
+ eqPos(cm.getCursor(), Pos(0, 3));
1396
+ eq(cm.getLine(0), "axxhicde");
1397
+ }, {value: "abcde\nfghij\nklmno\n"});
1398
+
1399
+ testCM("dirtyBit", function(cm) {
1400
+ eq(cm.isClean(), true);
1401
+ cm.replaceSelection("boo");
1402
+ eq(cm.isClean(), false);
1403
+ cm.undo();
1404
+ eq(cm.isClean(), true);
1405
+ cm.replaceSelection("boo");
1406
+ cm.replaceSelection("baz");
1407
+ cm.undo();
1408
+ eq(cm.isClean(), false);
1409
+ cm.markClean();
1410
+ eq(cm.isClean(), true);
1411
+ cm.undo();
1412
+ eq(cm.isClean(), false);
1413
+ cm.redo();
1414
+ eq(cm.isClean(), true);
1415
+ });
1416
+
1417
+ testCM("addKeyMap", function(cm) {
1418
+ function sendKey(code) {
1419
+ cm.triggerOnKeyDown({type: "keydown", keyCode: code,
1420
+ preventDefault: function(){}, stopPropagation: function(){}});
1421
+ }
1422
+
1423
+ sendKey(39);
1424
+ eqPos(cm.getCursor(), Pos(0, 1));
1425
+ var test = 0;
1426
+ var map1 = {Right: function() { ++test; }}, map2 = {Right: function() { test += 10; }}
1427
+ cm.addKeyMap(map1);
1428
+ sendKey(39);
1429
+ eqPos(cm.getCursor(), Pos(0, 1));
1430
+ eq(test, 1);
1431
+ cm.addKeyMap(map2, true);
1432
+ sendKey(39);
1433
+ eq(test, 2);
1434
+ cm.removeKeyMap(map1);
1435
+ sendKey(39);
1436
+ eq(test, 12);
1437
+ cm.removeKeyMap(map2);
1438
+ sendKey(39);
1439
+ eq(test, 12);
1440
+ eqPos(cm.getCursor(), Pos(0, 2));
1441
+ cm.addKeyMap({Right: function() { test = 55; }, name: "mymap"});
1442
+ sendKey(39);
1443
+ eq(test, 55);
1444
+ cm.removeKeyMap("mymap");
1445
+ sendKey(39);
1446
+ eqPos(cm.getCursor(), Pos(0, 3));
1447
+ }, {value: "abc"});
1448
+
1449
+ testCM("findPosH", function(cm) {
1450
+ forEach([{from: Pos(0, 0), to: Pos(0, 1), by: 1},
1451
+ {from: Pos(0, 0), to: Pos(0, 0), by: -1, hitSide: true},
1452
+ {from: Pos(0, 0), to: Pos(0, 4), by: 1, unit: "word"},
1453
+ {from: Pos(0, 0), to: Pos(0, 8), by: 2, unit: "word"},
1454
+ {from: Pos(0, 0), to: Pos(2, 0), by: 20, unit: "word", hitSide: true},
1455
+ {from: Pos(0, 7), to: Pos(0, 5), by: -1, unit: "word"},
1456
+ {from: Pos(0, 4), to: Pos(0, 8), by: 1, unit: "word"},
1457
+ {from: Pos(1, 0), to: Pos(1, 18), by: 3, unit: "word"},
1458
+ {from: Pos(1, 22), to: Pos(1, 5), by: -3, unit: "word"},
1459
+ {from: Pos(1, 15), to: Pos(1, 10), by: -5},
1460
+ {from: Pos(1, 15), to: Pos(1, 10), by: -5, unit: "column"},
1461
+ {from: Pos(1, 15), to: Pos(1, 0), by: -50, unit: "column", hitSide: true},
1462
+ {from: Pos(1, 15), to: Pos(1, 24), by: 50, unit: "column", hitSide: true},
1463
+ {from: Pos(1, 15), to: Pos(2, 0), by: 50, hitSide: true}], function(t) {
1464
+ var r = cm.findPosH(t.from, t.by, t.unit || "char");
1465
+ eqPos(r, t.to);
1466
+ eq(!!r.hitSide, !!t.hitSide);
1467
+ });
1468
+ }, {value: "line one\nline two.something.other\n"});
1469
+
1470
+ testCM("beforeChange", function(cm) {
1471
+ cm.on("beforeChange", function(cm, change) {
1472
+ var text = [];
1473
+ for (var i = 0; i < change.text.length; ++i)
1474
+ text.push(change.text[i].replace(/\s/g, "_"));
1475
+ change.update(null, null, text);
1476
+ });
1477
+ cm.setValue("hello, i am a\nnew document\n");
1478
+ eq(cm.getValue(), "hello,_i_am_a\nnew_document\n");
1479
+ CodeMirror.on(cm.getDoc(), "beforeChange", function(doc, change) {
1480
+ if (change.from.line == 0) change.cancel();
1481
+ });
1482
+ cm.setValue("oops"); // Canceled
1483
+ eq(cm.getValue(), "hello,_i_am_a\nnew_document\n");
1484
+ cm.replaceRange("hey hey hey", Pos(1, 0), Pos(2, 0));
1485
+ eq(cm.getValue(), "hello,_i_am_a\nhey_hey_hey");
1486
+ }, {value: "abcdefghijk"});
1487
+
1488
+ testCM("beforeChangeUndo", function(cm) {
1489
+ cm.setLine(0, "hi");
1490
+ cm.setLine(0, "bye");
1491
+ eq(cm.historySize().undo, 2);
1492
+ cm.on("beforeChange", function(cm, change) {
1493
+ is(!change.update);
1494
+ change.cancel();
1495
+ });
1496
+ cm.undo();
1497
+ eq(cm.historySize().undo, 0);
1498
+ eq(cm.getValue(), "bye\ntwo");
1499
+ }, {value: "one\ntwo"});
1500
+
1501
+ testCM("beforeSelectionChange", function(cm) {
1502
+ function notAtEnd(cm, pos) {
1503
+ var len = cm.getLine(pos.line).length;
1504
+ if (!len || pos.ch == len) return Pos(pos.line, pos.ch - 1);
1505
+ return pos;
1506
+ }
1507
+ cm.on("beforeSelectionChange", function(cm, sel) {
1508
+ sel.head = notAtEnd(cm, sel.head);
1509
+ sel.anchor = notAtEnd(cm, sel.anchor);
1510
+ });
1511
+
1512
+ addDoc(cm, 10, 10);
1513
+ cm.execCommand("goLineEnd");
1514
+ eqPos(cm.getCursor(), Pos(0, 9));
1515
+ cm.execCommand("selectAll");
1516
+ eqPos(cm.getCursor("start"), Pos(0, 0));
1517
+ eqPos(cm.getCursor("end"), Pos(9, 9));
1518
+ });
1519
+
1520
+ testCM("change_removedText", function(cm) {
1521
+ cm.setValue("abc\ndef");
1522
+
1523
+ var removedText;
1524
+ cm.on("change", function(cm, change) {
1525
+ removedText = [change.removed, change.next && change.next.removed];
1526
+ });
1527
+
1528
+ cm.operation(function() {
1529
+ cm.replaceRange("xyz", Pos(0, 0), Pos(1,1));
1530
+ cm.replaceRange("123", Pos(0,0));
1531
+ });
1532
+
1533
+ eq(removedText[0].join("\n"), "abc\nd");
1534
+ eq(removedText[1].join("\n"), "");
1535
+
1536
+ cm.undo();
1537
+ eq(removedText[0].join("\n"), "123");
1538
+ eq(removedText[1].join("\n"), "xyz");
1539
+
1540
+ cm.redo();
1541
+ eq(removedText[0].join("\n"), "abc\nd");
1542
+ eq(removedText[1].join("\n"), "");
1543
+ });
1544
+
1545
+ testCM("lineStyleFromMode", function(cm) {
1546
+ CodeMirror.defineMode("test_mode", function() {
1547
+ return {token: function(stream) {
1548
+ if (stream.match(/^\[[^\]]*\]/)) return "line-brackets";
1549
+ if (stream.match(/^\([^\]]*\)/)) return "line-background-parens";
1550
+ stream.match(/^\s+|^\S+/);
1551
+ }};
1552
+ });
1553
+ cm.setOption("mode", "test_mode");
1554
+ var bracketElts = byClassName(cm.getWrapperElement(), "brackets");
1555
+ eq(bracketElts.length, 1);
1556
+ eq(bracketElts[0].nodeName, "PRE");
1557
+ is(!/brackets.*brackets/.test(bracketElts[0].className));
1558
+ var parenElts = byClassName(cm.getWrapperElement(), "parens");
1559
+ eq(parenElts.length, 1);
1560
+ eq(parenElts[0].nodeName, "DIV");
1561
+ is(!/parens.*parens/.test(parenElts[0].className));
1562
+ }, {value: "line1: [br] [br]\nline2: (par) (par)\nline3: nothing"});