vapid 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (433) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +10 -0
  3. data/.gitmodules +6 -0
  4. data/.rspec +2 -0
  5. data/.rubocop.yml +133 -0
  6. data/.travis.yml +5 -0
  7. data/Gemfile +10 -0
  8. data/README.md +37 -0
  9. data/Rakefile +6 -0
  10. data/bin/console +14 -0
  11. data/bin/setup +8 -0
  12. data/exe/vapid +7 -0
  13. data/lib/vapid.rb +24 -0
  14. data/lib/vapid/assets/javascripts/vapid/admin.coffee +2 -0
  15. data/lib/vapid/assets/stylesheets/vapid/admin.scss +72 -0
  16. data/lib/vapid/builder.rb +70 -0
  17. data/lib/vapid/cli.rb +96 -0
  18. data/lib/vapid/controllers/admin_controller.rb +282 -0
  19. data/lib/vapid/controllers/project_controller.rb +41 -0
  20. data/lib/vapid/db/migrate/20170202182310_create_groups.rb +12 -0
  21. data/lib/vapid/db/migrate/20170202183017_create_records.rb +11 -0
  22. data/lib/vapid/db/migrate/20170202185150_create_users.rb +11 -0
  23. data/lib/vapid/directive.rb +168 -0
  24. data/lib/vapid/directives.rb +30 -0
  25. data/lib/vapid/directives/audio.rb +27 -0
  26. data/lib/vapid/directives/group.rb +71 -0
  27. data/lib/vapid/directives/hide.rb +11 -0
  28. data/lib/vapid/directives/href.rb +11 -0
  29. data/lib/vapid/directives/image.rb +14 -0
  30. data/lib/vapid/directives/richtext.rb +15 -0
  31. data/lib/vapid/directives/show.rb +11 -0
  32. data/lib/vapid/directives/text.rb +24 -0
  33. data/lib/vapid/directives/video.rb +28 -0
  34. data/lib/vapid/generator_template/.gitignore +21 -0
  35. data/lib/vapid/generator_template/Gemfile.tt +13 -0
  36. data/lib/vapid/generator_template/README.md +0 -0
  37. data/lib/vapid/generator_template/assets/favicon.ico +0 -0
  38. data/lib/vapid/generator_template/assets/images/.keep +0 -0
  39. data/lib/vapid/generator_template/assets/javascripts/.keep +0 -0
  40. data/lib/vapid/generator_template/assets/stylesheets/.keep +0 -0
  41. data/lib/vapid/generator_template/assets/stylesheets/application.css +120 -0
  42. data/lib/vapid/generator_template/config.ru +3 -0
  43. data/lib/vapid/generator_template/config/database.yml +12 -0
  44. data/lib/vapid/generator_template/config/settings.yml.tt +11 -0
  45. data/lib/vapid/generator_template/templates/index.html.erb +25 -0
  46. data/lib/vapid/generator_template/templates/layouts/default.html.erb +22 -0
  47. data/lib/vapid/models.rb +18 -0
  48. data/lib/vapid/models/group.rb +36 -0
  49. data/lib/vapid/models/record.rb +30 -0
  50. data/lib/vapid/models/user.rb +16 -0
  51. data/lib/vapid/server.rb +93 -0
  52. data/lib/vapid/settings.rb +13 -0
  53. data/lib/vapid/template.rb +79 -0
  54. data/lib/vapid/template/node.rb +91 -0
  55. data/lib/vapid/template/parser.rb +50 -0
  56. data/lib/vapid/vendor/semantic-ui/.versions +4 -0
  57. data/lib/vapid/vendor/semantic-ui/LICENSE +22 -0
  58. data/lib/vapid/vendor/semantic-ui/README.md +7 -0
  59. data/lib/vapid/vendor/semantic-ui/components/accordion.css +252 -0
  60. data/lib/vapid/vendor/semantic-ui/components/accordion.js +610 -0
  61. data/lib/vapid/vendor/semantic-ui/components/accordion.min.css +9 -0
  62. data/lib/vapid/vendor/semantic-ui/components/accordion.min.js +10 -0
  63. data/lib/vapid/vendor/semantic-ui/components/ad.css +275 -0
  64. data/lib/vapid/vendor/semantic-ui/components/ad.min.css +10 -0
  65. data/lib/vapid/vendor/semantic-ui/components/api.js +1167 -0
  66. data/lib/vapid/vendor/semantic-ui/components/api.min.js +10 -0
  67. data/lib/vapid/vendor/semantic-ui/components/breadcrumb.css +124 -0
  68. data/lib/vapid/vendor/semantic-ui/components/breadcrumb.min.css +9 -0
  69. data/lib/vapid/vendor/semantic-ui/components/button.css +3450 -0
  70. data/lib/vapid/vendor/semantic-ui/components/button.min.css +9 -0
  71. data/lib/vapid/vendor/semantic-ui/components/card.css +964 -0
  72. data/lib/vapid/vendor/semantic-ui/components/card.min.css +9 -0
  73. data/lib/vapid/vendor/semantic-ui/components/checkbox.css +625 -0
  74. data/lib/vapid/vendor/semantic-ui/components/checkbox.js +831 -0
  75. data/lib/vapid/vendor/semantic-ui/components/checkbox.min.css +9 -0
  76. data/lib/vapid/vendor/semantic-ui/components/checkbox.min.js +10 -0
  77. data/lib/vapid/vendor/semantic-ui/components/colorize.js +274 -0
  78. data/lib/vapid/vendor/semantic-ui/components/colorize.min.js +11 -0
  79. data/lib/vapid/vendor/semantic-ui/components/comment.css +270 -0
  80. data/lib/vapid/vendor/semantic-ui/components/comment.min.css +9 -0
  81. data/lib/vapid/vendor/semantic-ui/components/container.css +147 -0
  82. data/lib/vapid/vendor/semantic-ui/components/container.min.css +9 -0
  83. data/lib/vapid/vendor/semantic-ui/components/dimmer.css +200 -0
  84. data/lib/vapid/vendor/semantic-ui/components/dimmer.js +708 -0
  85. data/lib/vapid/vendor/semantic-ui/components/dimmer.min.css +9 -0
  86. data/lib/vapid/vendor/semantic-ui/components/dimmer.min.js +10 -0
  87. data/lib/vapid/vendor/semantic-ui/components/divider.css +260 -0
  88. data/lib/vapid/vendor/semantic-ui/components/divider.min.css +9 -0
  89. data/lib/vapid/vendor/semantic-ui/components/dropdown.css +1442 -0
  90. data/lib/vapid/vendor/semantic-ui/components/dropdown.js +3767 -0
  91. data/lib/vapid/vendor/semantic-ui/components/dropdown.min.css +9 -0
  92. data/lib/vapid/vendor/semantic-ui/components/dropdown.min.js +11 -0
  93. data/lib/vapid/vendor/semantic-ui/components/embed.css +166 -0
  94. data/lib/vapid/vendor/semantic-ui/components/embed.js +696 -0
  95. data/lib/vapid/vendor/semantic-ui/components/embed.min.css +9 -0
  96. data/lib/vapid/vendor/semantic-ui/components/embed.min.js +10 -0
  97. data/lib/vapid/vendor/semantic-ui/components/feed.css +296 -0
  98. data/lib/vapid/vendor/semantic-ui/components/feed.min.css +9 -0
  99. data/lib/vapid/vendor/semantic-ui/components/flag.css +1031 -0
  100. data/lib/vapid/vendor/semantic-ui/components/flag.min.css +9 -0
  101. data/lib/vapid/vendor/semantic-ui/components/form.css +1067 -0
  102. data/lib/vapid/vendor/semantic-ui/components/form.js +1603 -0
  103. data/lib/vapid/vendor/semantic-ui/components/form.min.css +9 -0
  104. data/lib/vapid/vendor/semantic-ui/components/form.min.js +10 -0
  105. data/lib/vapid/vendor/semantic-ui/components/grid.css +2002 -0
  106. data/lib/vapid/vendor/semantic-ui/components/grid.min.css +9 -0
  107. data/lib/vapid/vendor/semantic-ui/components/header.css +721 -0
  108. data/lib/vapid/vendor/semantic-ui/components/header.min.css +9 -0
  109. data/lib/vapid/vendor/semantic-ui/components/icon.css +3292 -0
  110. data/lib/vapid/vendor/semantic-ui/components/icon.min.css +9 -0
  111. data/lib/vapid/vendor/semantic-ui/components/image.css +306 -0
  112. data/lib/vapid/vendor/semantic-ui/components/image.min.css +9 -0
  113. data/lib/vapid/vendor/semantic-ui/components/input.css +510 -0
  114. data/lib/vapid/vendor/semantic-ui/components/input.min.css +9 -0
  115. data/lib/vapid/vendor/semantic-ui/components/item.css +486 -0
  116. data/lib/vapid/vendor/semantic-ui/components/item.min.css +9 -0
  117. data/lib/vapid/vendor/semantic-ui/components/label.css +1307 -0
  118. data/lib/vapid/vendor/semantic-ui/components/label.min.css +9 -0
  119. data/lib/vapid/vendor/semantic-ui/components/list.css +951 -0
  120. data/lib/vapid/vendor/semantic-ui/components/list.min.css +9 -0
  121. data/lib/vapid/vendor/semantic-ui/components/loader.css +347 -0
  122. data/lib/vapid/vendor/semantic-ui/components/loader.min.css +9 -0
  123. data/lib/vapid/vendor/semantic-ui/components/menu.css +2002 -0
  124. data/lib/vapid/vendor/semantic-ui/components/menu.min.css +1 -0
  125. data/lib/vapid/vendor/semantic-ui/components/message.css +477 -0
  126. data/lib/vapid/vendor/semantic-ui/components/message.min.css +9 -0
  127. data/lib/vapid/vendor/semantic-ui/components/modal.css +502 -0
  128. data/lib/vapid/vendor/semantic-ui/components/modal.js +913 -0
  129. data/lib/vapid/vendor/semantic-ui/components/modal.min.css +9 -0
  130. data/lib/vapid/vendor/semantic-ui/components/modal.min.js +10 -0
  131. data/lib/vapid/vendor/semantic-ui/components/nag.css +147 -0
  132. data/lib/vapid/vendor/semantic-ui/components/nag.js +507 -0
  133. data/lib/vapid/vendor/semantic-ui/components/nag.min.css +9 -0
  134. data/lib/vapid/vendor/semantic-ui/components/nag.min.js +10 -0
  135. data/lib/vapid/vendor/semantic-ui/components/popup.css +733 -0
  136. data/lib/vapid/vendor/semantic-ui/components/popup.js +1475 -0
  137. data/lib/vapid/vendor/semantic-ui/components/popup.min.css +9 -0
  138. data/lib/vapid/vendor/semantic-ui/components/popup.min.js +10 -0
  139. data/lib/vapid/vendor/semantic-ui/components/progress.css +516 -0
  140. data/lib/vapid/vendor/semantic-ui/components/progress.js +931 -0
  141. data/lib/vapid/vendor/semantic-ui/components/progress.min.css +9 -0
  142. data/lib/vapid/vendor/semantic-ui/components/progress.min.js +10 -0
  143. data/lib/vapid/vendor/semantic-ui/components/rail.css +152 -0
  144. data/lib/vapid/vendor/semantic-ui/components/rail.min.css +9 -0
  145. data/lib/vapid/vendor/semantic-ui/components/rating.css +263 -0
  146. data/lib/vapid/vendor/semantic-ui/components/rating.js +508 -0
  147. data/lib/vapid/vendor/semantic-ui/components/rating.min.css +9 -0
  148. data/lib/vapid/vendor/semantic-ui/components/rating.min.js +10 -0
  149. data/lib/vapid/vendor/semantic-ui/components/reset.css +424 -0
  150. data/lib/vapid/vendor/semantic-ui/components/reset.min.css +9 -0
  151. data/lib/vapid/vendor/semantic-ui/components/reveal.css +284 -0
  152. data/lib/vapid/vendor/semantic-ui/components/reveal.min.css +9 -0
  153. data/lib/vapid/vendor/semantic-ui/components/search.css +408 -0
  154. data/lib/vapid/vendor/semantic-ui/components/search.js +1442 -0
  155. data/lib/vapid/vendor/semantic-ui/components/search.min.css +9 -0
  156. data/lib/vapid/vendor/semantic-ui/components/search.min.js +10 -0
  157. data/lib/vapid/vendor/semantic-ui/components/segment.css +798 -0
  158. data/lib/vapid/vendor/semantic-ui/components/segment.min.css +9 -0
  159. data/lib/vapid/vendor/semantic-ui/components/shape.css +157 -0
  160. data/lib/vapid/vendor/semantic-ui/components/shape.js +921 -0
  161. data/lib/vapid/vendor/semantic-ui/components/shape.min.css +9 -0
  162. data/lib/vapid/vendor/semantic-ui/components/shape.min.js +10 -0
  163. data/lib/vapid/vendor/semantic-ui/components/sidebar.css +634 -0
  164. data/lib/vapid/vendor/semantic-ui/components/sidebar.js +1036 -0
  165. data/lib/vapid/vendor/semantic-ui/components/sidebar.min.css +9 -0
  166. data/lib/vapid/vendor/semantic-ui/components/sidebar.min.js +10 -0
  167. data/lib/vapid/vendor/semantic-ui/components/site.css +160 -0
  168. data/lib/vapid/vendor/semantic-ui/components/site.js +487 -0
  169. data/lib/vapid/vendor/semantic-ui/components/site.min.css +9 -0
  170. data/lib/vapid/vendor/semantic-ui/components/site.min.js +10 -0
  171. data/lib/vapid/vendor/semantic-ui/components/state.js +708 -0
  172. data/lib/vapid/vendor/semantic-ui/components/state.min.js +10 -0
  173. data/lib/vapid/vendor/semantic-ui/components/statistic.css +569 -0
  174. data/lib/vapid/vendor/semantic-ui/components/statistic.min.css +9 -0
  175. data/lib/vapid/vendor/semantic-ui/components/step.css +623 -0
  176. data/lib/vapid/vendor/semantic-ui/components/step.min.css +9 -0
  177. data/lib/vapid/vendor/semantic-ui/components/sticky.css +78 -0
  178. data/lib/vapid/vendor/semantic-ui/components/sticky.js +942 -0
  179. data/lib/vapid/vendor/semantic-ui/components/sticky.min.css +9 -0
  180. data/lib/vapid/vendor/semantic-ui/components/sticky.min.js +10 -0
  181. data/lib/vapid/vendor/semantic-ui/components/tab.css +91 -0
  182. data/lib/vapid/vendor/semantic-ui/components/tab.js +952 -0
  183. data/lib/vapid/vendor/semantic-ui/components/tab.min.css +9 -0
  184. data/lib/vapid/vendor/semantic-ui/components/tab.min.js +10 -0
  185. data/lib/vapid/vendor/semantic-ui/components/table.css +1108 -0
  186. data/lib/vapid/vendor/semantic-ui/components/table.min.css +9 -0
  187. data/lib/vapid/vendor/semantic-ui/components/transition.css +1964 -0
  188. data/lib/vapid/vendor/semantic-ui/components/transition.js +1095 -0
  189. data/lib/vapid/vendor/semantic-ui/components/transition.min.css +9 -0
  190. data/lib/vapid/vendor/semantic-ui/components/transition.min.js +10 -0
  191. data/lib/vapid/vendor/semantic-ui/components/video.css +125 -0
  192. data/lib/vapid/vendor/semantic-ui/components/video.js +532 -0
  193. data/lib/vapid/vendor/semantic-ui/components/video.min.css +10 -0
  194. data/lib/vapid/vendor/semantic-ui/components/video.min.js +11 -0
  195. data/lib/vapid/vendor/semantic-ui/components/visibility.js +1288 -0
  196. data/lib/vapid/vendor/semantic-ui/components/visibility.min.js +10 -0
  197. data/lib/vapid/vendor/semantic-ui/components/visit.js +517 -0
  198. data/lib/vapid/vendor/semantic-ui/components/visit.min.js +11 -0
  199. data/lib/vapid/vendor/semantic-ui/package.js +34 -0
  200. data/lib/vapid/vendor/semantic-ui/package.json +20 -0
  201. data/lib/vapid/vendor/semantic-ui/semantic.css +36844 -0
  202. data/lib/vapid/vendor/semantic-ui/semantic.js +22617 -0
  203. data/lib/vapid/vendor/semantic-ui/semantic.min.css +364 -0
  204. data/lib/vapid/vendor/semantic-ui/semantic.min.js +19 -0
  205. data/lib/vapid/vendor/semantic-ui/themes/default/assets/fonts/icons.eot +0 -0
  206. data/lib/vapid/vendor/semantic-ui/themes/default/assets/fonts/icons.otf +0 -0
  207. data/lib/vapid/vendor/semantic-ui/themes/default/assets/fonts/icons.svg +2671 -0
  208. data/lib/vapid/vendor/semantic-ui/themes/default/assets/fonts/icons.ttf +0 -0
  209. data/lib/vapid/vendor/semantic-ui/themes/default/assets/fonts/icons.woff +0 -0
  210. data/lib/vapid/vendor/semantic-ui/themes/default/assets/fonts/icons.woff2 +0 -0
  211. data/lib/vapid/vendor/semantic-ui/themes/default/assets/images/flags.png +0 -0
  212. data/lib/vapid/vendor/trix/.blade.yml +45 -0
  213. data/lib/vapid/vendor/trix/.github/ISSUE_TEMPLATE.md +13 -0
  214. data/lib/vapid/vendor/trix/.gitignore +3 -0
  215. data/lib/vapid/vendor/trix/.ruby-version +1 -0
  216. data/lib/vapid/vendor/trix/.travis.yml +6 -0
  217. data/lib/vapid/vendor/trix/CONDUCT.md +79 -0
  218. data/lib/vapid/vendor/trix/Gemfile +17 -0
  219. data/lib/vapid/vendor/trix/Gemfile.lock +152 -0
  220. data/lib/vapid/vendor/trix/LICENSE +20 -0
  221. data/lib/vapid/vendor/trix/README.md +382 -0
  222. data/lib/vapid/vendor/trix/assets/index.html +55 -0
  223. data/lib/vapid/vendor/trix/assets/trix-core.coffee +2 -0
  224. data/lib/vapid/vendor/trix/assets/trix.coffee +3 -0
  225. data/lib/vapid/vendor/trix/assets/trix.scss +5 -0
  226. data/lib/vapid/vendor/trix/assets/trix/banner/index.coffee.erb +3 -0
  227. data/lib/vapid/vendor/trix/assets/trix/banner/index.scss.erb +3 -0
  228. data/lib/vapid/vendor/trix/assets/trix/banner/index.txt.erb +3 -0
  229. data/lib/vapid/vendor/trix/assets/trix/images/README.md +6 -0
  230. data/lib/vapid/vendor/trix/assets/trix/images/attach.svg +5 -0
  231. data/lib/vapid/vendor/trix/assets/trix/images/bold.svg +5 -0
  232. data/lib/vapid/vendor/trix/assets/trix/images/bullets.svg +5 -0
  233. data/lib/vapid/vendor/trix/assets/trix/images/code.svg +5 -0
  234. data/lib/vapid/vendor/trix/assets/trix/images/heading_1.svg +5 -0
  235. data/lib/vapid/vendor/trix/assets/trix/images/italic.svg +5 -0
  236. data/lib/vapid/vendor/trix/assets/trix/images/link.svg +6 -0
  237. data/lib/vapid/vendor/trix/assets/trix/images/nesting_level_decrease.svg +5 -0
  238. data/lib/vapid/vendor/trix/assets/trix/images/nesting_level_increase.svg +5 -0
  239. data/lib/vapid/vendor/trix/assets/trix/images/numbers.svg +5 -0
  240. data/lib/vapid/vendor/trix/assets/trix/images/quote.svg +5 -0
  241. data/lib/vapid/vendor/trix/assets/trix/images/redo.svg +5 -0
  242. data/lib/vapid/vendor/trix/assets/trix/images/remove.svg +4 -0
  243. data/lib/vapid/vendor/trix/assets/trix/images/strike.svg +6 -0
  244. data/lib/vapid/vendor/trix/assets/trix/images/trash.svg +5 -0
  245. data/lib/vapid/vendor/trix/assets/trix/images/undo.svg +5 -0
  246. data/lib/vapid/vendor/trix/assets/trix/stylesheets/attachments.scss +112 -0
  247. data/lib/vapid/vendor/trix/assets/trix/stylesheets/content.scss +88 -0
  248. data/lib/vapid/vendor/trix/assets/trix/stylesheets/editor.scss +8 -0
  249. data/lib/vapid/vendor/trix/assets/trix/stylesheets/icons.scss +14 -0
  250. data/lib/vapid/vendor/trix/assets/trix/stylesheets/media-queries.scss +7 -0
  251. data/lib/vapid/vendor/trix/assets/trix/stylesheets/toolbar.scss +194 -0
  252. data/lib/vapid/vendor/trix/bin/blade +16 -0
  253. data/lib/vapid/vendor/trix/bin/ci +21 -0
  254. data/lib/vapid/vendor/trix/bin/rackup +16 -0
  255. data/lib/vapid/vendor/trix/bin/rake +16 -0
  256. data/lib/vapid/vendor/trix/bin/release +139 -0
  257. data/lib/vapid/vendor/trix/bin/setup +69 -0
  258. data/lib/vapid/vendor/trix/bin/update-status-image +100 -0
  259. data/lib/vapid/vendor/trix/bower.json +34 -0
  260. data/lib/vapid/vendor/trix/config.ru +32 -0
  261. data/lib/vapid/vendor/trix/dist/trix-core.js +11 -0
  262. data/lib/vapid/vendor/trix/dist/trix.css +286 -0
  263. data/lib/vapid/vendor/trix/dist/trix.js +20 -0
  264. data/lib/vapid/vendor/trix/package.json +29 -0
  265. data/lib/vapid/vendor/trix/polyfills/polyfills.coffee +3 -0
  266. data/lib/vapid/vendor/trix/polyfills/set.coffee +24 -0
  267. data/lib/vapid/vendor/trix/polyfills/vendor/CustomElements.js +1029 -0
  268. data/lib/vapid/vendor/trix/polyfills/vendor/README.md +2 -0
  269. data/lib/vapid/vendor/trix/polyfills/vendor/promise.js +228 -0
  270. data/lib/vapid/vendor/trix/src/trix/VERSION +1 -0
  271. data/lib/vapid/vendor/trix/src/trix/config/block_attributes.coffee +37 -0
  272. data/lib/vapid/vendor/trix/src/trix/config/css.coffee +12 -0
  273. data/lib/vapid/vendor/trix/src/trix/config/file_size_formatting.coffee +22 -0
  274. data/lib/vapid/vendor/trix/src/trix/config/index.coffee +9 -0
  275. data/lib/vapid/vendor/trix/src/trix/config/lang.coffee +26 -0
  276. data/lib/vapid/vendor/trix/src/trix/config/selection_elements.coffee +26 -0
  277. data/lib/vapid/vendor/trix/src/trix/config/serialization.coffee +63 -0
  278. data/lib/vapid/vendor/trix/src/trix/config/text_attributes.coffee +25 -0
  279. data/lib/vapid/vendor/trix/src/trix/config/toolbar.coffee +41 -0
  280. data/lib/vapid/vendor/trix/src/trix/config/undo_interval.coffee +7 -0
  281. data/lib/vapid/vendor/trix/src/trix/controllers/attachment_editor_controller.coffee +104 -0
  282. data/lib/vapid/vendor/trix/src/trix/controllers/composition_controller.coffee +117 -0
  283. data/lib/vapid/vendor/trix/src/trix/controllers/controller.coffee +3 -0
  284. data/lib/vapid/vendor/trix/src/trix/controllers/editor_controller.coffee +369 -0
  285. data/lib/vapid/vendor/trix/src/trix/controllers/input/composition_input.coffee +57 -0
  286. data/lib/vapid/vendor/trix/src/trix/controllers/input_controller.coffee +473 -0
  287. data/lib/vapid/vendor/trix/src/trix/controllers/toolbar_controller.coffee +173 -0
  288. data/lib/vapid/vendor/trix/src/trix/core/basic_object.coffee +44 -0
  289. data/lib/vapid/vendor/trix/src/trix/core/collections/element_store.coffee +21 -0
  290. data/lib/vapid/vendor/trix/src/trix/core/collections/hash.coffee +98 -0
  291. data/lib/vapid/vendor/trix/src/trix/core/collections/index.coffee +4 -0
  292. data/lib/vapid/vendor/trix/src/trix/core/collections/object_group.coffee +37 -0
  293. data/lib/vapid/vendor/trix/src/trix/core/collections/object_map.coffee +10 -0
  294. data/lib/vapid/vendor/trix/src/trix/core/helpers/arrays.coffee +34 -0
  295. data/lib/vapid/vendor/trix/src/trix/core/helpers/config.coffee +23 -0
  296. data/lib/vapid/vendor/trix/src/trix/core/helpers/custom_elements.coffee +45 -0
  297. data/lib/vapid/vendor/trix/src/trix/core/helpers/dom.coffee +185 -0
  298. data/lib/vapid/vendor/trix/src/trix/core/helpers/extend.coffee +4 -0
  299. data/lib/vapid/vendor/trix/src/trix/core/helpers/functions.coffee +3 -0
  300. data/lib/vapid/vendor/trix/src/trix/core/helpers/global.coffee +23 -0
  301. data/lib/vapid/vendor/trix/src/trix/core/helpers/index.coffee +10 -0
  302. data/lib/vapid/vendor/trix/src/trix/core/helpers/objects.coffee +11 -0
  303. data/lib/vapid/vendor/trix/src/trix/core/helpers/ranges.coffee +33 -0
  304. data/lib/vapid/vendor/trix/src/trix/core/helpers/selection.coffee +25 -0
  305. data/lib/vapid/vendor/trix/src/trix/core/helpers/strings.coffee +46 -0
  306. data/lib/vapid/vendor/trix/src/trix/core/index.coffee +4 -0
  307. data/lib/vapid/vendor/trix/src/trix/core/object.coffee +33 -0
  308. data/lib/vapid/vendor/trix/src/trix/core/utilities/index.coffee +2 -0
  309. data/lib/vapid/vendor/trix/src/trix/core/utilities/operation.coffee +37 -0
  310. data/lib/vapid/vendor/trix/src/trix/core/utilities/utf16_string.coffee +93 -0
  311. data/lib/vapid/vendor/trix/src/trix/elements/trix_editor_element.coffee +166 -0
  312. data/lib/vapid/vendor/trix/src/trix/elements/trix_toolbar_element.coffee +28 -0
  313. data/lib/vapid/vendor/trix/src/trix/index.coffee.erb +14 -0
  314. data/lib/vapid/vendor/trix/src/trix/inspector/control_element.coffee +60 -0
  315. data/lib/vapid/vendor/trix/src/trix/inspector/debugger.coffee +104 -0
  316. data/lib/vapid/vendor/trix/src/trix/inspector/element.coffee +86 -0
  317. data/lib/vapid/vendor/trix/src/trix/inspector/index.coffee +17 -0
  318. data/lib/vapid/vendor/trix/src/trix/inspector/polyfills/vendor/details-element-polyfill.js +5 -0
  319. data/lib/vapid/vendor/trix/src/trix/inspector/templates/debug.jst.eco +17 -0
  320. data/lib/vapid/vendor/trix/src/trix/inspector/templates/document.jst.eco +33 -0
  321. data/lib/vapid/vendor/trix/src/trix/inspector/templates/performance.jst.eco +10 -0
  322. data/lib/vapid/vendor/trix/src/trix/inspector/templates/render.jst.eco +1 -0
  323. data/lib/vapid/vendor/trix/src/trix/inspector/templates/selection.jst.eco +5 -0
  324. data/lib/vapid/vendor/trix/src/trix/inspector/templates/undo.jst.eco +13 -0
  325. data/lib/vapid/vendor/trix/src/trix/inspector/view.coffee +58 -0
  326. data/lib/vapid/vendor/trix/src/trix/inspector/views/debug_view.coffee +33 -0
  327. data/lib/vapid/vendor/trix/src/trix/inspector/views/document_view.coffee +12 -0
  328. data/lib/vapid/vendor/trix/src/trix/inspector/views/performance_view.coffee +51 -0
  329. data/lib/vapid/vendor/trix/src/trix/inspector/views/render_view.coffee +21 -0
  330. data/lib/vapid/vendor/trix/src/trix/inspector/views/selection_view.coffee +33 -0
  331. data/lib/vapid/vendor/trix/src/trix/inspector/views/undo_view.coffee +12 -0
  332. data/lib/vapid/vendor/trix/src/trix/inspector/watchdog/deserializer.coffee +55 -0
  333. data/lib/vapid/vendor/trix/src/trix/inspector/watchdog/index.coffee +5 -0
  334. data/lib/vapid/vendor/trix/src/trix/inspector/watchdog/player.coffee +60 -0
  335. data/lib/vapid/vendor/trix/src/trix/inspector/watchdog/player_controller.coffee +43 -0
  336. data/lib/vapid/vendor/trix/src/trix/inspector/watchdog/player_element.coffee +32 -0
  337. data/lib/vapid/vendor/trix/src/trix/inspector/watchdog/player_view.coffee +133 -0
  338. data/lib/vapid/vendor/trix/src/trix/inspector/watchdog/recorder.coffee +82 -0
  339. data/lib/vapid/vendor/trix/src/trix/inspector/watchdog/recording.coffee +54 -0
  340. data/lib/vapid/vendor/trix/src/trix/inspector/watchdog/serializer.coffee +61 -0
  341. data/lib/vapid/vendor/trix/src/trix/models/attachment.coffee +157 -0
  342. data/lib/vapid/vendor/trix/src/trix/models/attachment_manager.coffee +24 -0
  343. data/lib/vapid/vendor/trix/src/trix/models/attachment_piece.coffee +47 -0
  344. data/lib/vapid/vendor/trix/src/trix/models/block.coffee +230 -0
  345. data/lib/vapid/vendor/trix/src/trix/models/composition.coffee +521 -0
  346. data/lib/vapid/vendor/trix/src/trix/models/document.coffee +538 -0
  347. data/lib/vapid/vendor/trix/src/trix/models/editor.coffee +141 -0
  348. data/lib/vapid/vendor/trix/src/trix/models/html_parser.coffee +335 -0
  349. data/lib/vapid/vendor/trix/src/trix/models/line_break_insertion.coffee +31 -0
  350. data/lib/vapid/vendor/trix/src/trix/models/location_mapper.coffee +156 -0
  351. data/lib/vapid/vendor/trix/src/trix/models/managed_attachment.coffee +28 -0
  352. data/lib/vapid/vendor/trix/src/trix/models/piece.coffee +95 -0
  353. data/lib/vapid/vendor/trix/src/trix/models/point_mapper.coffee +28 -0
  354. data/lib/vapid/vendor/trix/src/trix/models/selection_manager.coffee +129 -0
  355. data/lib/vapid/vendor/trix/src/trix/models/splittable_list.coffee +168 -0
  356. data/lib/vapid/vendor/trix/src/trix/models/string_piece.coffee +49 -0
  357. data/lib/vapid/vendor/trix/src/trix/models/text.coffee +168 -0
  358. data/lib/vapid/vendor/trix/src/trix/models/undo_manager.coffee +40 -0
  359. data/lib/vapid/vendor/trix/src/trix/observers/mutation_observer.coffee +131 -0
  360. data/lib/vapid/vendor/trix/src/trix/observers/selection_change_observer.coffee +56 -0
  361. data/lib/vapid/vendor/trix/src/trix/operations/file_verification_operation.coffee +15 -0
  362. data/lib/vapid/vendor/trix/src/trix/operations/image_preload_operation.coffee +15 -0
  363. data/lib/vapid/vendor/trix/src/trix/views/attachment_view.coffee +99 -0
  364. data/lib/vapid/vendor/trix/src/trix/views/block_view.coffee +37 -0
  365. data/lib/vapid/vendor/trix/src/trix/views/document_view.coffee +68 -0
  366. data/lib/vapid/vendor/trix/src/trix/views/object_group_view.coffee +23 -0
  367. data/lib/vapid/vendor/trix/src/trix/views/object_view.coffee +86 -0
  368. data/lib/vapid/vendor/trix/src/trix/views/piece_view.coffee +97 -0
  369. data/lib/vapid/vendor/trix/src/trix/views/previewable_attachment_view.coffee +49 -0
  370. data/lib/vapid/vendor/trix/src/trix/views/text_view.coffee +30 -0
  371. data/lib/vapid/vendor/trix/test/.gitignore +1 -0
  372. data/lib/vapid/vendor/trix/test/src/system/attachment_test.coffee +70 -0
  373. data/lib/vapid/vendor/trix/test/src/system/basic_input_test.coffee +68 -0
  374. data/lib/vapid/vendor/trix/test/src/system/block_formatting_test.coffee +602 -0
  375. data/lib/vapid/vendor/trix/test/src/system/caching_test.coffee +21 -0
  376. data/lib/vapid/vendor/trix/test/src/system/composition_input_test.coffee +138 -0
  377. data/lib/vapid/vendor/trix/test/src/system/cursor_movement_test.coffee +54 -0
  378. data/lib/vapid/vendor/trix/test/src/system/custom_element_test.coffee +314 -0
  379. data/lib/vapid/vendor/trix/test/src/system/html_loading_test.coffee +62 -0
  380. data/lib/vapid/vendor/trix/test/src/system/html_replacement_test.coffee +101 -0
  381. data/lib/vapid/vendor/trix/test/src/system/installation_process_test.coffee +59 -0
  382. data/lib/vapid/vendor/trix/test/src/system/list_formatting_test.coffee +70 -0
  383. data/lib/vapid/vendor/trix/test/src/system/mutation_input_test.coffee +73 -0
  384. data/lib/vapid/vendor/trix/test/src/system/pasting_test.coffee +215 -0
  385. data/lib/vapid/vendor/trix/test/src/system/text_formatting_test.coffee +151 -0
  386. data/lib/vapid/vendor/trix/test/src/system/undo_test.coffee +48 -0
  387. data/lib/vapid/vendor/trix/test/src/test.coffee +16 -0
  388. data/lib/vapid/vendor/trix/test/src/test_helpers/assertions.coffee +38 -0
  389. data/lib/vapid/vendor/trix/test/src/test_helpers/editor_helpers.coffee +37 -0
  390. data/lib/vapid/vendor/trix/test/src/test_helpers/fixtures/editor_empty.jst.eco +1 -0
  391. data/lib/vapid/vendor/trix/test/src/test_helpers/fixtures/editor_html.jst.eco +2 -0
  392. data/lib/vapid/vendor/trix/test/src/test_helpers/fixtures/editor_in_table.jst.eco +7 -0
  393. data/lib/vapid/vendor/trix/test/src/test_helpers/fixtures/editor_with_block_styles.jst.eco +6 -0
  394. data/lib/vapid/vendor/trix/test/src/test_helpers/fixtures/editor_with_bold_styles.jst.eco +7 -0
  395. data/lib/vapid/vendor/trix/test/src/test_helpers/fixtures/editor_with_image.jst.eco +2 -0
  396. data/lib/vapid/vendor/trix/test/src/test_helpers/fixtures/editor_with_styled_content.jst.eco +7 -0
  397. data/lib/vapid/vendor/trix/test/src/test_helpers/fixtures/editor_with_toolbar_and_input.jst.eco +5 -0
  398. data/lib/vapid/vendor/trix/test/src/test_helpers/fixtures/fixtures.coffee +536 -0
  399. data/lib/vapid/vendor/trix/test/src/test_helpers/fixtures/logo.png +0 -0
  400. data/lib/vapid/vendor/trix/test/src/test_helpers/index.coffee +18 -0
  401. data/lib/vapid/vendor/trix/test/src/test_helpers/input_helpers.coffee +183 -0
  402. data/lib/vapid/vendor/trix/test/src/test_helpers/selection_helpers.coffee +91 -0
  403. data/lib/vapid/vendor/trix/test/src/test_helpers/test_helpers.coffee +72 -0
  404. data/lib/vapid/vendor/trix/test/src/test_helpers/test_stubs.coffee +31 -0
  405. data/lib/vapid/vendor/trix/test/src/test_helpers/toolbar_helpers.coffee +45 -0
  406. data/lib/vapid/vendor/trix/test/src/unit/attachment_test.coffee +23 -0
  407. data/lib/vapid/vendor/trix/test/src/unit/block_test.coffee +22 -0
  408. data/lib/vapid/vendor/trix/test/src/unit/composition_test.coffee +13 -0
  409. data/lib/vapid/vendor/trix/test/src/unit/document_test.coffee +11 -0
  410. data/lib/vapid/vendor/trix/test/src/unit/document_view_test.coffee +6 -0
  411. data/lib/vapid/vendor/trix/test/src/unit/html_parser_test.coffee +162 -0
  412. data/lib/vapid/vendor/trix/test/src/unit/location_mapper_test.coffee +185 -0
  413. data/lib/vapid/vendor/trix/test/src/unit/mutation_observer_test.coffee +84 -0
  414. data/lib/vapid/vendor/trix/test/src/unit/serialization_test.coffee +7 -0
  415. data/lib/vapid/vendor/trix/test/src/unit/string_change_summary_test.coffee +57 -0
  416. data/lib/vapid/vendor/trix/test/src/unit/text_test.coffee +19 -0
  417. data/lib/vapid/vendor/trix/test/vendor/rangy-core.js +3845 -0
  418. data/lib/vapid/vendor/trix/test/vendor/rangy-textrange.js +1930 -0
  419. data/lib/vapid/version.rb +4 -0
  420. data/lib/vapid/views/admin/install.html.erb +19 -0
  421. data/lib/vapid/views/admin/login.html.erb +11 -0
  422. data/lib/vapid/views/admin/overview/index.html.erb +1 -0
  423. data/lib/vapid/views/admin/records/_form.erb +9 -0
  424. data/lib/vapid/views/admin/records/edit.html.erb +5 -0
  425. data/lib/vapid/views/admin/records/index.html.erb +38 -0
  426. data/lib/vapid/views/admin/records/new.html.erb +3 -0
  427. data/lib/vapid/views/errors/404.html.erb +1 -0
  428. data/lib/vapid/views/errors/500.html.erb +1 -0
  429. data/lib/vapid/views/layouts/admin.html.erb +41 -0
  430. data/lib/vapid/views/layouts/admin_form.html.erb +22 -0
  431. data/lib/vapid/views/layouts/error.html.erb +11 -0
  432. data/vapid.gemspec +48 -0
  433. metadata +811 -0
@@ -0,0 +1,49 @@
1
+ #= require trix/views/attachment_view
2
+
3
+ {makeElement} = Trix
4
+
5
+ class Trix.PreviewableAttachmentView extends Trix.AttachmentView
6
+ constructor: ->
7
+ super
8
+ @attachment.previewDelegate = this
9
+
10
+ createContentNodes: ->
11
+ @image = makeElement
12
+ tagName: "img"
13
+ attributes:
14
+ src: ""
15
+ data:
16
+ trixMutable: true
17
+
18
+ @refresh(@image)
19
+ [@image]
20
+
21
+ refresh: (image) ->
22
+ image ?= @findElement()?.querySelector("img")
23
+ @updateAttributesForImage(image) if image
24
+
25
+ updateAttributesForImage: (image) ->
26
+ url = @attachment.getURL()
27
+ previewURL = @attachment.getPreviewURL()
28
+ image.src = previewURL or url
29
+
30
+ if previewURL is url
31
+ image.removeAttribute("data-trix-serialized-attributes")
32
+ else
33
+ serializedAttributes = JSON.stringify(src: url)
34
+ image.setAttribute("data-trix-serialized-attributes", serializedAttributes)
35
+
36
+ width = @attachment.getWidth()
37
+ height = @attachment.getHeight()
38
+
39
+ image.width = width if width?
40
+ image.height = height if height?
41
+
42
+ storeKey = ["imageElement", @attachment.id, image.src, image.width, image.height].join("/")
43
+ image.dataset.trixStoreKey = storeKey
44
+
45
+ # Attachment delegate
46
+
47
+ attachmentDidChangePreviewURL: ->
48
+ @refresh(@image)
49
+ @refresh()
@@ -0,0 +1,30 @@
1
+ #= require trix/views/piece_view
2
+
3
+ class Trix.TextView extends Trix.ObjectView
4
+ constructor: ->
5
+ super
6
+ @text = @object
7
+ {@textConfig} = @options
8
+
9
+ createNodes: ->
10
+ nodes = []
11
+ pieces = Trix.ObjectGroup.groupObjects(@getPieces())
12
+ lastIndex = pieces.length - 1
13
+
14
+ for piece, index in pieces
15
+ context = {}
16
+ context.isFirst = true if index is 0
17
+ context.isLast = true if index is lastIndex
18
+ context.followsWhitespace = true if endsWithWhitespace(previousPiece)
19
+
20
+ view = @findOrCreateCachedChildView(Trix.PieceView, piece, {@textConfig, context})
21
+ nodes.push(view.getNodes()...)
22
+
23
+ previousPiece = piece
24
+ nodes
25
+
26
+ getPieces: ->
27
+ piece for piece in @text.getPieces() when not piece.hasAttribute("blockBreak")
28
+
29
+ endsWithWhitespace = (piece) ->
30
+ /\s$/.test(piece?.toString())
@@ -0,0 +1 @@
1
+ /dist
@@ -0,0 +1,70 @@
1
+ {after, assert, clickElement, defer, dragToCoordinates, moveCursor, pressKey, test, testGroup, triggerEvent, typeCharacters} = Trix.TestHelpers
2
+
3
+ testGroup "Attachments", template: "editor_with_image", ->
4
+ test "moving an image by drag and drop", (expectDocument) ->
5
+ typeCharacters "!", ->
6
+ moveCursor direction: "right", times: 1, (coordinates) ->
7
+ img = document.activeElement.querySelector("img")
8
+ triggerEvent(img, "mousedown")
9
+ defer ->
10
+ dragToCoordinates coordinates, ->
11
+ expectDocument "!a#{Trix.OBJECT_REPLACEMENT_CHARACTER}b\n"
12
+
13
+ test "removing an image", (expectDocument) ->
14
+ after 20, ->
15
+ clickElement getFigure(), ->
16
+ closeButton = getFigure().querySelector(".#{Trix.config.css.classNames.attachment.removeButton.split(" ").join(".")}")
17
+ clickElement closeButton, ->
18
+ expectDocument "ab\n"
19
+
20
+ test "editing an image caption", (expectDocument) ->
21
+ after 20, ->
22
+ clickElement findElement("figure"), ->
23
+ clickElement findElement("figcaption"), ->
24
+ defer ->
25
+ assert.ok findElement("textarea")
26
+ findElement("textarea").focus()
27
+ findElement("textarea").value = "my caption"
28
+ pressKey "return", ->
29
+ assert.notOk findElement("textarea")
30
+ assert.textAttributes [2, 3], caption: "my caption"
31
+ assert.locationRange index: 0, offset: 3
32
+ expectDocument "ab#{Trix.OBJECT_REPLACEMENT_CHARACTER}\n"
33
+
34
+ test "editing an attachment caption with no filename", (done) ->
35
+ after 20, ->
36
+ # Caption is initially empty
37
+ captionElement = findElement("figcaption")
38
+ assert.equal captionElement.clientHeight, 0
39
+ assert.equal getCaptionContent(captionElement), ""
40
+
41
+ clickElement findElement("figure"), ->
42
+ # Caption prompt is displayed when editing attachment
43
+ captionElement = findElement("figcaption")
44
+ assert.ok captionElement.clientHeight > 0
45
+ assert.equal getCaptionContent(captionElement), Trix.config.lang.captionPrompt
46
+ done()
47
+
48
+ getFigure = ->
49
+ findElement("figure")
50
+
51
+ findElement = (selector) ->
52
+ getEditorElement().querySelector(selector)
53
+
54
+ getCaptionContent = (element) ->
55
+ element.textContent or getPseudoContent(element)
56
+
57
+
58
+ getPseudoContent = (element) ->
59
+ before = getComputedStyle(element, "::before").content
60
+ after = getComputedStyle(element, "::after").content
61
+
62
+ content =
63
+ if before and before isnt "none"
64
+ before
65
+ else if after and after isnt "none"
66
+ after
67
+ else
68
+ ""
69
+
70
+ content.replace(/^['"]/, "").replace(/['"]$/, "")
@@ -0,0 +1,68 @@
1
+ {assert, defer, dragToCoordinates, expandSelection, insertNode, moveCursor, pressKey, selectAll, test, testGroup, triggerEvent, typeCharacters} = Trix.TestHelpers
2
+
3
+ testGroup "Basic input", template: "editor_empty", ->
4
+ test "typing", (expectDocument) ->
5
+ typeCharacters "abc", ->
6
+ expectDocument "abc\n"
7
+
8
+ test "backspacing", (expectDocument) ->
9
+ typeCharacters "abc\b", ->
10
+ assert.locationRange(index: 0, offset: 2)
11
+ expectDocument "ab\n"
12
+
13
+ test "pressing delete", (expectDocument) ->
14
+ typeCharacters "ab", ->
15
+ moveCursor "left", ->
16
+ pressKey "delete", ->
17
+ expectDocument "a\n"
18
+
19
+ test "pressing return", (expectDocument) ->
20
+ typeCharacters "ab", ->
21
+ pressKey "return", ->
22
+ typeCharacters "c", ->
23
+ expectDocument "ab\nc\n"
24
+
25
+ test "cursor left", (expectDocument) ->
26
+ typeCharacters "ac", ->
27
+ moveCursor "left", ->
28
+ typeCharacters "b", ->
29
+ expectDocument "abc\n"
30
+
31
+ test "replace entire document", (expectDocument) ->
32
+ typeCharacters "abc", ->
33
+ selectAll ->
34
+ typeCharacters "d", ->
35
+ expectDocument "d\n"
36
+
37
+ test "remove entire document", (expectDocument) ->
38
+ typeCharacters "abc", ->
39
+ selectAll ->
40
+ typeCharacters "\b", ->
41
+ expectDocument "\n"
42
+
43
+ test "drag text", (expectDocument) ->
44
+ typeCharacters "abc", ->
45
+ moveCursor direction: "left", times: 2, (coordinates) ->
46
+ moveCursor "right", ->
47
+ expandSelection "right", ->
48
+ dragToCoordinates coordinates, ->
49
+ expectDocument "acb\n"
50
+
51
+ test "inserting newline after cursor (control + o)", (expectDocument) ->
52
+ typeCharacters "ab", ->
53
+ moveCursor "left", ->
54
+ triggerEvent(document.activeElement, "keydown", charCode: 0, keyCode: 79, which: 79, ctrlKey: true)
55
+ defer ->
56
+ assert.locationRange index: 0, offset: 1
57
+ expectDocument "a\nb\n"
58
+
59
+ test "inserting ó with control + alt + o (AltGr)", (expectDocument) ->
60
+ typeCharacters "ab", ->
61
+ moveCursor "left", ->
62
+ if triggerEvent(document.activeElement, "keydown", charCode: 0, keyCode: 79, which: 79, altKey: true, ctrlKey: true)
63
+ triggerEvent(document.activeElement, "keypress", charCode: 243, keyCode: 243, which: 243, altKey: true, ctrlKey: true)
64
+ insertNode(document.createTextNode("ó"))
65
+
66
+ defer ->
67
+ assert.locationRange index: 0, offset: 2
68
+ expectDocument "aób\n"
@@ -0,0 +1,602 @@
1
+ {assert, clickToolbarButton, defer, expandSelection, isToolbarButtonActive, isToolbarButtonDisabled, moveCursor, pressKey, replaceDocument, selectAll, test, testGroup, typeCharacters} = Trix.TestHelpers
2
+
3
+ testGroup "Block formatting", template: "editor_empty", ->
4
+ test "applying block attributes", (done) ->
5
+ typeCharacters "abc", ->
6
+ clickToolbarButton attribute: "quote", ->
7
+ assert.blockAttributes([0, 4], ["quote"])
8
+ assert.ok isToolbarButtonActive(attribute: "quote")
9
+ clickToolbarButton attribute: "code", ->
10
+ assert.blockAttributes([0, 4], ["quote", "code"])
11
+ assert.ok isToolbarButtonActive(attribute: "code")
12
+ clickToolbarButton attribute: "code", ->
13
+ assert.blockAttributes([0, 4], ["quote"])
14
+ assert.notOk isToolbarButtonActive(attribute: "code")
15
+ assert.ok isToolbarButtonActive(attribute: "quote")
16
+ done()
17
+
18
+ test "applying block attributes to text after newline", (done) ->
19
+ typeCharacters "a\nbc", ->
20
+ clickToolbarButton attribute: "quote", ->
21
+ assert.blockAttributes([0, 2], [])
22
+ assert.blockAttributes([2, 4], ["quote"])
23
+ done()
24
+
25
+ test "applying block attributes to text between newlines", (done) ->
26
+ typeCharacters """
27
+ ab
28
+ def
29
+ ghi
30
+ j
31
+ """, ->
32
+ moveCursor direction: "left", times: 2, ->
33
+ expandSelection direction: "left", times: 5, ->
34
+ clickToolbarButton attribute: "quote", ->
35
+ assert.blockAttributes([0, 3], [])
36
+ assert.blockAttributes([3, 11], ["quote"])
37
+ assert.blockAttributes([11, 13], [])
38
+ done()
39
+
40
+ test "applying bullets to text with newlines", (done) ->
41
+ typeCharacters """
42
+ abc
43
+ def
44
+ ghi
45
+ jkl
46
+ mno
47
+ """, ->
48
+ moveCursor direction: "left", times: 2, ->
49
+ expandSelection direction: "left", times: 15, ->
50
+ clickToolbarButton attribute: "bullet", ->
51
+ assert.blockAttributes([0, 4], ["bulletList", "bullet"])
52
+ assert.blockAttributes([4, 8], ["bulletList", "bullet"])
53
+ assert.blockAttributes([8, 12], ["bulletList", "bullet"])
54
+ assert.blockAttributes([12, 16], ["bulletList", "bullet"])
55
+ assert.blockAttributes([16, 20], ["bulletList", "bullet"])
56
+ done()
57
+
58
+ test "applying block attributes to adjacent unformatted blocks consolidates them", (done) ->
59
+ document = new Trix.Document [
60
+ new Trix.Block(Trix.Text.textForStringWithAttributes("1"), ["bulletList", "bullet"])
61
+ new Trix.Block(Trix.Text.textForStringWithAttributes("a"), [])
62
+ new Trix.Block(Trix.Text.textForStringWithAttributes("b"), [])
63
+ new Trix.Block(Trix.Text.textForStringWithAttributes("c"), [])
64
+ new Trix.Block(Trix.Text.textForStringWithAttributes("2"), ["bulletList", "bullet"])
65
+ new Trix.Block(Trix.Text.textForStringWithAttributes("3"), ["bulletList", "bullet"])
66
+ ]
67
+
68
+ replaceDocument(document)
69
+ getEditorController().setLocationRange([{index: 0, offset: 0}, {index: 5, offset: 1}])
70
+ defer ->
71
+ clickToolbarButton attribute: "quote", ->
72
+ assert.blockAttributes([0, 2], ["bulletList", "bullet", "quote"])
73
+ assert.blockAttributes([2, 8], ["quote"])
74
+ assert.blockAttributes([8, 10], ["bulletList", "bullet", "quote"])
75
+ assert.blockAttributes([10, 12], ["bulletList", "bullet", "quote"])
76
+ done()
77
+
78
+ test "breaking out of the end of a block", (done) ->
79
+ typeCharacters "abc", ->
80
+ clickToolbarButton attribute: "quote", ->
81
+ typeCharacters "\n\n", ->
82
+ document = getDocument()
83
+ assert.equal document.getBlockCount(), 2
84
+
85
+ block = document.getBlockAtIndex(0)
86
+ assert.deepEqual block.getAttributes(), ["quote"]
87
+ assert.equal block.toString(), "abc\n"
88
+
89
+ block = document.getBlockAtIndex(1)
90
+ assert.deepEqual block.getAttributes(), []
91
+ assert.equal block.toString(), "\n"
92
+
93
+ assert.locationRange(index: 1, offset: 0)
94
+ done()
95
+
96
+
97
+ test "breaking out of the middle of a block before character", (done) ->
98
+ # * = cursor
99
+ #
100
+ # ab
101
+ # *c
102
+ #
103
+ typeCharacters "abc", ->
104
+ clickToolbarButton attribute: "quote", ->
105
+ moveCursor "left", ->
106
+ typeCharacters "\n\n", ->
107
+ document = getDocument()
108
+ assert.equal document.getBlockCount(), 3
109
+
110
+ block = document.getBlockAtIndex(0)
111
+ assert.deepEqual block.getAttributes(), ["quote"]
112
+ assert.equal block.toString(), "ab\n"
113
+
114
+ block = document.getBlockAtIndex(1)
115
+ assert.deepEqual block.getAttributes(), []
116
+ assert.equal block.toString(), "\n"
117
+
118
+ block = document.getBlockAtIndex(2)
119
+ assert.deepEqual block.getAttributes(), ["quote"]
120
+ assert.equal block.toString(), "c\n"
121
+
122
+ assert.locationRange(index: 2, offset: 0)
123
+ done()
124
+
125
+ test "breaking out of the middle of a block before newline", (done) ->
126
+ # * = cursor
127
+ #
128
+ # ab
129
+ # *
130
+ # c
131
+ #
132
+ typeCharacters "abc", ->
133
+ clickToolbarButton attribute: "quote", ->
134
+ moveCursor "left", ->
135
+ typeCharacters "\n", ->
136
+ moveCursor "left", ->
137
+ typeCharacters "\n\n", ->
138
+ document = getDocument()
139
+ assert.equal document.getBlockCount(), 3
140
+
141
+ block = document.getBlockAtIndex(0)
142
+ assert.deepEqual block.getAttributes(), ["quote"]
143
+ assert.equal block.toString(), "ab\n"
144
+
145
+ block = document.getBlockAtIndex(1)
146
+ assert.deepEqual block.getAttributes(), []
147
+ assert.equal block.toString(), "\n"
148
+
149
+ block = document.getBlockAtIndex(2)
150
+ assert.deepEqual block.getAttributes(), ["quote"]
151
+ assert.equal block.toString(), "c\n"
152
+
153
+ done()
154
+
155
+ test "breaking out of a formatted block with adjacent non-formatted blocks", (expectDocument) ->
156
+ # * = cursor
157
+ #
158
+ # a
159
+ # b*
160
+ # c
161
+ document = new Trix.Document [
162
+ new Trix.Block(Trix.Text.textForStringWithAttributes("a"), [])
163
+ new Trix.Block(Trix.Text.textForStringWithAttributes("b"), ["quote"])
164
+ new Trix.Block(Trix.Text.textForStringWithAttributes("c"), [])
165
+ ]
166
+
167
+ replaceDocument(document)
168
+ getEditor().setSelectedRange(3)
169
+
170
+ typeCharacters "\n\n", ->
171
+ document = getDocument()
172
+ assert.equal document.getBlockCount(), 4
173
+ assert.blockAttributes([0, 1], [])
174
+ assert.blockAttributes([2, 3], ["quote"])
175
+ assert.blockAttributes([4, 5], [])
176
+ assert.blockAttributes([5, 6], [])
177
+ expectDocument("a\nb\n\nc\n")
178
+
179
+ test "breaking out a block after newline at offset 0", (done) ->
180
+ # * = cursor
181
+ #
182
+ #
183
+ # *a
184
+ #
185
+ typeCharacters "a", ->
186
+ clickToolbarButton attribute: "quote", ->
187
+ moveCursor "left", ->
188
+ typeCharacters "\n\n", ->
189
+ document = getDocument()
190
+ assert.equal document.getBlockCount(), 2
191
+
192
+ block = document.getBlockAtIndex(0)
193
+ assert.deepEqual block.getAttributes(), []
194
+ assert.equal block.toString(), "\n"
195
+
196
+ block = document.getBlockAtIndex(1)
197
+ assert.deepEqual block.getAttributes(), ["quote"]
198
+ assert.equal block.toString(), "a\n"
199
+ assert.locationRange(index: 1, offset: 0)
200
+
201
+ done()
202
+
203
+ test "deleting the only non-block-break character in a block", (done) ->
204
+ typeCharacters "ab", ->
205
+ clickToolbarButton attribute: "quote", ->
206
+ typeCharacters "\b\b", ->
207
+ assert.blockAttributes([0, 1], ["quote"])
208
+ done()
209
+
210
+ test "backspacing a quote", (done) ->
211
+ clickToolbarButton attribute: "quote", ->
212
+ assert.blockAttributes([0, 1], ["quote"])
213
+ pressKey "backspace", ->
214
+ assert.blockAttributes([0, 1], [])
215
+ done()
216
+
217
+ test "backspacing a nested quote", (done) ->
218
+ clickToolbarButton attribute: "quote", ->
219
+ clickToolbarButton action: "increaseNestingLevel", ->
220
+ assert.blockAttributes([0, 1], ["quote", "quote"])
221
+ pressKey "backspace", ->
222
+ assert.blockAttributes([0, 1], ["quote"])
223
+ pressKey "backspace", ->
224
+ assert.blockAttributes([0, 1], [])
225
+ done()
226
+
227
+ test "backspacing a list item", (done) ->
228
+ clickToolbarButton attribute: "bullet", ->
229
+ assert.blockAttributes([0, 1], ["bulletList", "bullet"])
230
+ pressKey "backspace", ->
231
+ assert.blockAttributes([0, 0], [])
232
+ done()
233
+
234
+ test "backspacing a nested list item", (expectDocument) ->
235
+ clickToolbarButton attribute: "bullet", ->
236
+ typeCharacters "a\n", ->
237
+ clickToolbarButton action: "increaseNestingLevel", ->
238
+ assert.blockAttributes([2, 3], ["bulletList", "bullet", "bulletList", "bullet"])
239
+ pressKey "backspace", ->
240
+ assert.blockAttributes([2, 3], ["bulletList", "bullet"])
241
+ expectDocument("a\n\n")
242
+
243
+ test "backspacing a list item inside a quote", (done) ->
244
+ clickToolbarButton attribute: "quote", ->
245
+ clickToolbarButton attribute: "bullet", ->
246
+ assert.blockAttributes([0, 1], ["quote", "bulletList", "bullet"])
247
+ pressKey "backspace", ->
248
+ assert.blockAttributes([0, 1], ["quote"])
249
+ pressKey "backspace", ->
250
+ assert.blockAttributes([0, 1], [])
251
+ done()
252
+
253
+ test "backspacing selected nested list items", (expectDocument) ->
254
+ clickToolbarButton attribute: "bullet", ->
255
+ typeCharacters "a\n", ->
256
+ clickToolbarButton action: "increaseNestingLevel", ->
257
+ typeCharacters "b", ->
258
+ getSelectionManager().setLocationRange([{index: 0, offset: 0}, {index: 1, offset: 1}])
259
+ pressKey "backspace", ->
260
+ assert.blockAttributes([0, 1], ["bulletList", "bullet"])
261
+ expectDocument("\n")
262
+
263
+ test "backspace selection spanning formatted blocks", (expectDocument) ->
264
+ clickToolbarButton attribute: "quote", ->
265
+ typeCharacters "ab\n\n", ->
266
+ clickToolbarButton attribute: "code", ->
267
+ typeCharacters "cd", ->
268
+ getSelectionManager().setLocationRange([{index: 0, offset: 1}, {index: 1, offset: 1}])
269
+ getComposition().deleteInDirection("backward")
270
+ assert.blockAttributes([0, 2], ["quote"])
271
+ expectDocument("ad\n")
272
+
273
+ test "backspace selection spanning and entire formatted block and a formatted block", (expectDocument) ->
274
+ clickToolbarButton attribute: "quote", ->
275
+ typeCharacters "ab\n\n", ->
276
+ clickToolbarButton attribute: "code", ->
277
+ typeCharacters "cd", ->
278
+ getSelectionManager().setLocationRange([{index: 0, offset: 0}, {index: 1, offset: 1}])
279
+ getComposition().deleteInDirection("backward")
280
+ assert.blockAttributes([0, 2], ["code"])
281
+ expectDocument("d\n")
282
+
283
+ test "increasing list level", (done) ->
284
+ assert.ok isToolbarButtonDisabled(action: "increaseNestingLevel")
285
+ assert.ok isToolbarButtonDisabled(action: "decreaseNestingLevel")
286
+ clickToolbarButton attribute: "bullet", ->
287
+ assert.ok isToolbarButtonDisabled(action: "increaseNestingLevel")
288
+ assert.notOk isToolbarButtonDisabled(action: "decreaseNestingLevel")
289
+ typeCharacters "a\n", ->
290
+ assert.notOk isToolbarButtonDisabled(action: "increaseNestingLevel")
291
+ assert.notOk isToolbarButtonDisabled(action: "decreaseNestingLevel")
292
+ clickToolbarButton action: "increaseNestingLevel", ->
293
+ typeCharacters "b", ->
294
+ assert.ok isToolbarButtonDisabled(action: "increaseNestingLevel")
295
+ assert.notOk isToolbarButtonDisabled(action: "decreaseNestingLevel")
296
+ assert.blockAttributes([0, 2], ["bulletList", "bullet"])
297
+ assert.blockAttributes([2, 4], ["bulletList", "bullet", "bulletList", "bullet"])
298
+ done()
299
+
300
+ test "changing list type", (done) ->
301
+ clickToolbarButton attribute: "bullet", ->
302
+ assert.blockAttributes([0, 1], ["bulletList", "bullet"])
303
+ clickToolbarButton attribute: "number", ->
304
+ assert.blockAttributes([0, 1], ["numberList", "number"])
305
+ done()
306
+
307
+ test "adding bullet to heading block", (done) ->
308
+ clickToolbarButton attribute: "heading1", ->
309
+ clickToolbarButton attribute: "bullet", ->
310
+ assert.ok isToolbarButtonActive(attribute: "heading1")
311
+ assert.blockAttributes([1, 2], [])
312
+ done()
313
+
314
+ test "removing bullet from heading block", (done) ->
315
+ clickToolbarButton attribute: "bullet", ->
316
+ clickToolbarButton attribute: "heading1", ->
317
+ assert.ok isToolbarButtonDisabled(attribute: "bullet")
318
+ done()
319
+
320
+ test "breaking out of heading in list", (expectDocument) ->
321
+ clickToolbarButton attribute: "bullet", ->
322
+ clickToolbarButton attribute: "heading1", ->
323
+ assert.ok isToolbarButtonActive(attribute: "heading1")
324
+ typeCharacters "abc", ->
325
+ typeCharacters "\n", ->
326
+ assert.ok isToolbarButtonActive(attribute: "bullet")
327
+ document = getDocument()
328
+ assert.equal document.getBlockCount(), 2
329
+ assert.blockAttributes([0, 4], ["bulletList", "bullet", "heading1"])
330
+ assert.blockAttributes([4, 5], ["bulletList", "bullet"])
331
+ expectDocument("abc\n\n")
332
+
333
+ test "breaking out of middle of heading block", (expectDocument) ->
334
+ clickToolbarButton attribute: "heading1", ->
335
+ typeCharacters "abc", ->
336
+ assert.ok isToolbarButtonActive(attribute: "heading1")
337
+ moveCursor direction: "left", times: 1, ->
338
+ typeCharacters "\n", ->
339
+ document = getDocument()
340
+ assert.equal document.getBlockCount(), 2
341
+ assert.blockAttributes([0, 3], ["heading1"])
342
+ assert.blockAttributes([3, 4], ["heading1"])
343
+ expectDocument("ab\nc\n")
344
+
345
+ test "breaking out of middle of heading block with preceding blocks", (expectDocument) ->
346
+ document = new Trix.Document [
347
+ new Trix.Block(Trix.Text.textForStringWithAttributes("a"), ["heading1"])
348
+ new Trix.Block(Trix.Text.textForStringWithAttributes("b"), [])
349
+ new Trix.Block(Trix.Text.textForStringWithAttributes("cd"), ["heading1"])
350
+ ]
351
+
352
+ replaceDocument(document)
353
+ getEditor().setSelectedRange(5)
354
+ assert.ok isToolbarButtonActive(attribute: "heading1")
355
+
356
+ typeCharacters "\n", ->
357
+ document = getDocument()
358
+ assert.equal document.getBlockCount(), 4
359
+ assert.blockAttributes([0, 1], ["heading1"])
360
+ assert.blockAttributes([2, 3], [])
361
+ assert.blockAttributes([4, 5], ["heading1"])
362
+ assert.blockAttributes([6, 7], ["heading1"])
363
+ expectDocument("a\nb\nc\nd\n")
364
+
365
+ test "breaking out of end of heading block with preceding blocks", (expectDocument) ->
366
+ document = new Trix.Document [
367
+ new Trix.Block(Trix.Text.textForStringWithAttributes("a"), ["heading1"])
368
+ new Trix.Block(Trix.Text.textForStringWithAttributes("b"), [])
369
+ new Trix.Block(Trix.Text.textForStringWithAttributes("cd"), ["heading1"])
370
+ ]
371
+
372
+ replaceDocument(document)
373
+ getEditor().setSelectedRange(6)
374
+ assert.ok isToolbarButtonActive(attribute: "heading1")
375
+
376
+ typeCharacters "\n", ->
377
+ document = getDocument()
378
+ assert.equal document.getBlockCount(), 4
379
+ assert.blockAttributes([0, 1], ["heading1"])
380
+ assert.blockAttributes([2, 3], [])
381
+ assert.blockAttributes([4, 6], ["heading1"])
382
+ assert.blockAttributes([7, 8], [])
383
+ expectDocument("a\nb\ncd\n\n")
384
+
385
+ test "inserting newline before heading", (done) ->
386
+ document = new Trix.Document [
387
+ new Trix.Block(Trix.Text.textForStringWithAttributes("\n"), [])
388
+ new Trix.Block(Trix.Text.textForStringWithAttributes("abc"), ["heading1"])
389
+ ]
390
+
391
+ replaceDocument(document)
392
+ getEditor().setSelectedRange(0)
393
+
394
+ typeCharacters "\n", ->
395
+ document = getDocument()
396
+ assert.equal document.getBlockCount(), 2
397
+
398
+ block = document.getBlockAtIndex(0)
399
+ assert.deepEqual block.getAttributes(), []
400
+ assert.equal block.toString(), "\n\n\n"
401
+
402
+ block = document.getBlockAtIndex(1)
403
+ assert.deepEqual block.getAttributes(), ["heading1"]
404
+ assert.equal block.toString(), "abc\n"
405
+
406
+ done()
407
+
408
+ test "inserting multiple newlines before heading", (done) ->
409
+ document = new Trix.Document [
410
+ new Trix.Block(Trix.Text.textForStringWithAttributes("\n"), [])
411
+ new Trix.Block(Trix.Text.textForStringWithAttributes("abc"), ["heading1"])
412
+ ]
413
+
414
+ replaceDocument(document)
415
+ getEditor().setSelectedRange(0)
416
+
417
+ typeCharacters "\n\n", ->
418
+ document = getDocument()
419
+ assert.equal document.getBlockCount(), 2
420
+
421
+ block = document.getBlockAtIndex(0)
422
+ assert.deepEqual block.getAttributes(), []
423
+ assert.equal block.toString(), "\n\n\n\n"
424
+
425
+ block = document.getBlockAtIndex(1)
426
+ assert.deepEqual block.getAttributes(), ["heading1"]
427
+ assert.equal block.toString(), "abc\n"
428
+ done()
429
+
430
+ test "inserting multiple newlines before formatted block", (expectDocument) ->
431
+ document = new Trix.Document [
432
+ new Trix.Block(Trix.Text.textForStringWithAttributes("\n"), [])
433
+ new Trix.Block(Trix.Text.textForStringWithAttributes("abc"), ["quote"])
434
+ ]
435
+
436
+ replaceDocument(document)
437
+ getEditor().setSelectedRange(1)
438
+
439
+ typeCharacters "\n\n", ->
440
+ document = getDocument()
441
+ assert.equal document.getBlockCount(), 2
442
+ assert.blockAttributes([0, 1], [])
443
+ assert.blockAttributes([2, 3], [])
444
+ assert.blockAttributes([4, 6], ["quote"])
445
+ assert.locationRange(index: 0, offset: 3)
446
+ expectDocument("\n\n\n\nabc\n")
447
+
448
+ test "inserting newline after heading with text in following block", (expectDocument) ->
449
+ document = new Trix.Document [
450
+ new Trix.Block(Trix.Text.textForStringWithAttributes("ab"), ["heading1"])
451
+ new Trix.Block(Trix.Text.textForStringWithAttributes("cd"), [])
452
+ ]
453
+
454
+ replaceDocument(document)
455
+ getEditor().setSelectedRange(2)
456
+
457
+ typeCharacters "\n", ->
458
+ document = getDocument()
459
+ assert.equal document.getBlockCount(), 3
460
+ assert.blockAttributes([0, 2], ["heading1"])
461
+ assert.blockAttributes([3, 4], [])
462
+ assert.blockAttributes([5, 6], [])
463
+ expectDocument("ab\n\ncd\n")
464
+
465
+ test "backspacing a newline in an empty block with adjacent formatted blocks", (expectDocument) ->
466
+ document = new Trix.Document [
467
+ new Trix.Block(Trix.Text.textForStringWithAttributes("abc"), ["heading1"])
468
+ new Trix.Block
469
+ new Trix.Block(Trix.Text.textForStringWithAttributes("d"), ["heading1"])
470
+ ]
471
+
472
+ replaceDocument(document)
473
+ getEditor().setSelectedRange(4)
474
+
475
+ pressKey "backspace", ->
476
+ document = getDocument()
477
+ assert.equal document.getBlockCount(), 2
478
+ assert.blockAttributes([0, 1], ["heading1"])
479
+ assert.blockAttributes([2, 3], ["heading1"])
480
+ expectDocument("abc\nd\n")
481
+
482
+ test "backspacing a newline at beginning of non-formatted block", (expectDocument) ->
483
+ document = new Trix.Document [
484
+ new Trix.Block(Trix.Text.textForStringWithAttributes("ab"), ["heading1"])
485
+ new Trix.Block(Trix.Text.textForStringWithAttributes("\ncd"), [])
486
+ ]
487
+
488
+ replaceDocument(document)
489
+ getEditor().setSelectedRange(3)
490
+
491
+ pressKey "backspace", ->
492
+ document = getDocument()
493
+ assert.equal document.getBlockCount(), 2
494
+ assert.blockAttributes([0, 2], ["heading1"])
495
+ assert.blockAttributes([3, 5], [])
496
+ expectDocument("ab\ncd\n")
497
+
498
+ test "inserting newline after single character header", (expectDocument) ->
499
+ clickToolbarButton attribute: "heading1", ->
500
+ typeCharacters "a", ->
501
+ typeCharacters "\n", ->
502
+ document = getDocument()
503
+ assert.equal document.getBlockCount(), 2
504
+ assert.blockAttributes([0, 1], ["heading1"])
505
+ expectDocument("a\n\n")
506
+
507
+ test "terminal attributes are only added once", (expectDocument) ->
508
+ replaceDocument new Trix.Document [
509
+ new Trix.Block(Trix.Text.textForStringWithAttributes("a"), [])
510
+ new Trix.Block(Trix.Text.textForStringWithAttributes("b"), ["heading1"])
511
+ new Trix.Block(Trix.Text.textForStringWithAttributes("c"), [])
512
+ ]
513
+
514
+ selectAll ->
515
+ clickToolbarButton attribute: "heading1", ->
516
+ assert.equal getDocument().getBlockCount(), 3
517
+ assert.blockAttributes([0, 1], ["heading1"])
518
+ assert.blockAttributes([2, 3], ["heading1"])
519
+ assert.blockAttributes([4, 5], ["heading1"])
520
+ expectDocument("a\nb\nc\n")
521
+
522
+ test "terminal attributes replace existing terminal attributes", (expectDocument) ->
523
+ replaceDocument new Trix.Document [
524
+ new Trix.Block(Trix.Text.textForStringWithAttributes("a"), [])
525
+ new Trix.Block(Trix.Text.textForStringWithAttributes("b"), ["heading1"])
526
+ new Trix.Block(Trix.Text.textForStringWithAttributes("c"), [])
527
+ ]
528
+
529
+ selectAll ->
530
+ clickToolbarButton attribute: "code", ->
531
+ assert.equal getDocument().getBlockCount(), 3
532
+ assert.blockAttributes([0, 1], ["code"])
533
+ assert.blockAttributes([2, 3], ["code"])
534
+ assert.blockAttributes([4, 5], ["code"])
535
+ expectDocument("a\nb\nc\n")
536
+
537
+ test "code blocks preserve newlines", (expectDocument) ->
538
+ typeCharacters "a\nb", ->
539
+ selectAll ->
540
+ clickToolbarButton attribute: "code", ->
541
+ assert.equal getDocument().getBlockCount(), 1
542
+ assert.blockAttributes([0, 3], ["code"])
543
+ expectDocument("a\nb\n")
544
+
545
+ test "code blocks are not indentable", (done) ->
546
+ clickToolbarButton attribute: "code", ->
547
+ assert.notOk isToolbarButtonActive(action: "increaseNestingLevel")
548
+ done()
549
+
550
+ test "code blocks are terminal", (done) ->
551
+ clickToolbarButton attribute: "code", ->
552
+ assert.ok isToolbarButtonDisabled(attribute: "quote")
553
+ assert.ok isToolbarButtonDisabled(attribute: "heading1")
554
+ assert.ok isToolbarButtonDisabled(attribute: "bullet")
555
+ assert.ok isToolbarButtonDisabled(attribute: "number")
556
+ assert.notOk isToolbarButtonDisabled(attribute: "code")
557
+ assert.notOk isToolbarButtonDisabled(attribute: "bold")
558
+ assert.notOk isToolbarButtonDisabled(attribute: "italic")
559
+ done()
560
+
561
+ test "unindenting a code block inside a bullet", (expectDocument) ->
562
+ clickToolbarButton attribute: "bullet", ->
563
+ clickToolbarButton attribute: "code", ->
564
+ typeCharacters "a", ->
565
+ clickToolbarButton action: "decreaseNestingLevel", ->
566
+ document = getDocument()
567
+ assert.equal document.getBlockCount(), 1
568
+ assert.blockAttributes([0, 1], ["code"])
569
+ expectDocument("a\n")
570
+
571
+ test "indenting a heading inside a bullet", (expectDocument) ->
572
+ clickToolbarButton attribute: "bullet", ->
573
+ typeCharacters "a", ->
574
+ typeCharacters "\n", ->
575
+ clickToolbarButton attribute: "heading1", ->
576
+ typeCharacters "b", ->
577
+ clickToolbarButton action: "increaseNestingLevel", ->
578
+ document = getDocument()
579
+ assert.equal document.getBlockCount(), 2
580
+ assert.blockAttributes([0, 1], ["bulletList", "bullet"])
581
+ assert.blockAttributes([2, 3], ["bulletList", "bullet", "bulletList", "bullet", "heading1"])
582
+ expectDocument("a\nb\n")
583
+
584
+ test "indenting a quote inside a bullet", (expectDocument) ->
585
+ clickToolbarButton attribute: "bullet", ->
586
+ clickToolbarButton attribute: "quote", ->
587
+ clickToolbarButton action: "increaseNestingLevel", ->
588
+ document = getDocument()
589
+ assert.equal document.getBlockCount(), 1
590
+ assert.blockAttributes([0, 1], ["bulletList", "bullet", "quote", "quote"])
591
+ expectDocument("\n")
592
+
593
+ test "list indentation constraints consider the list type", (expectDocument) ->
594
+ clickToolbarButton attribute: "bullet", ->
595
+ typeCharacters "a\n\n", ->
596
+ clickToolbarButton attribute: "number", ->
597
+ clickToolbarButton action: "increaseNestingLevel", ->
598
+ document = getDocument()
599
+ assert.equal document.getBlockCount(), 2
600
+ assert.blockAttributes([0, 1], ["bulletList", "bullet"])
601
+ assert.blockAttributes([2, 3], ["numberList", "number"])
602
+ expectDocument("a\n\n")