scarpe 0.2.2 → 0.4.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 (378) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +7 -1
  3. data/.yardopts +1 -0
  4. data/CHANGELOG.md +52 -6
  5. data/Gemfile +2 -1
  6. data/Gemfile.lock +20 -6
  7. data/LICENSE.txt +7 -1
  8. data/README.md +100 -21
  9. data/Rakefile +68 -1
  10. data/examples/Edit_box_Styles.rb +8 -0
  11. data/examples/Kerning.rb +7 -0
  12. data/examples/animate.rb +20 -0
  13. data/examples/arrow.rb +10 -0
  14. data/examples/border.rb +11 -0
  15. data/examples/btn_tooltip.rb +7 -0
  16. data/examples/button_style_changed.rb +7 -0
  17. data/examples/button_styles_default.rb +6 -0
  18. data/examples/check.rb +2 -0
  19. data/examples/download_and_show_image.rb +3 -0
  20. data/examples/flags/finland.rb +15 -0
  21. data/examples/flags/italy.rb +11 -0
  22. data/examples/flags/mauritius.rb +14 -0
  23. data/examples/font_family.rb +17 -0
  24. data/examples/font_shorthand.rb +9 -0
  25. data/examples/gen.rb +12 -8
  26. data/examples/highlander.rb +3 -3
  27. data/examples/legacy/README.md +6 -0
  28. data/examples/legacy/not_checked/shoes-contrib/basic/shoes-notes.rb +1 -1
  29. data/examples/legacy/not_checked/shoes-manual/append.rb +10 -0
  30. data/examples/legacy/not_checked/shoes-manual/background_change.rb +12 -0
  31. data/examples/legacy/not_checked/shoes-manual/background_pattern.rb +5 -0
  32. data/examples/legacy/not_checked/shoes-manual/basic_app.rb +8 -0
  33. data/examples/legacy/not_checked/shoes-manual/border.rb +9 -0
  34. data/examples/legacy/not_checked/shoes-manual/builtins/FONTS.rb +5 -0
  35. data/examples/legacy/not_checked/shoes-manual/builtins/ask.rb +2 -0
  36. data/examples/legacy/not_checked/shoes-manual/builtins/ask_color.rb +5 -0
  37. data/examples/legacy/not_checked/shoes-manual/builtins/ask_open_file.rb +5 -0
  38. data/examples/legacy/not_checked/shoes-manual/builtins/ask_save_folder.rb +2 -0
  39. data/examples/legacy/not_checked/shoes-manual/builtins/confirm.rb +4 -0
  40. data/examples/legacy/not_checked/shoes-manual/builtins/debug.rb +2 -0
  41. data/examples/legacy/not_checked/shoes-manual/builtins/info.rb +3 -0
  42. data/examples/legacy/not_checked/shoes-manual/button.rb +9 -0
  43. data/examples/legacy/not_checked/shoes-manual/clear.rb +7 -0
  44. data/examples/legacy/not_checked/shoes-manual/custom_header.rb +13 -0
  45. data/examples/legacy/not_checked/shoes-manual/displace.rb +14 -0
  46. data/examples/legacy/not_checked/shoes-manual/edit_box.rb +8 -0
  47. data/examples/legacy/not_checked/shoes-manual/fill_pattern.rb +5 -0
  48. data/examples/legacy/not_checked/shoes-manual/fonts.rb +7 -0
  49. data/examples/legacy/not_checked/shoes-manual/gutter.rb +6 -0
  50. data/examples/legacy/not_checked/shoes-manual/image_web.rb +4 -0
  51. data/examples/legacy/not_checked/shoes-manual/keypress.rb +7 -0
  52. data/examples/legacy/not_checked/shoes-manual/list_box.rb +10 -0
  53. data/examples/legacy/not_checked/shoes-manual/motion.rb +10 -0
  54. data/examples/legacy/not_checked/shoes-manual/mouse.rb +8 -0
  55. data/examples/legacy/not_checked/shoes-manual/move.rb +14 -0
  56. data/examples/legacy/not_checked/shoes-manual/nested_ovals.rb +8 -0
  57. data/examples/legacy/not_checked/shoes-manual/oval.rb +7 -0
  58. data/examples/legacy/not_checked/shoes-manual/ovals.rb +6 -0
  59. data/examples/legacy/not_checked/shoes-manual/ovals_image.rb +8 -0
  60. data/examples/legacy/not_checked/shoes-manual/prepend.rb +7 -0
  61. data/examples/legacy/not_checked/shoes-manual/progress_bar.rb +10 -0
  62. data/examples/legacy/not_checked/shoes-manual/radio.rb +18 -0
  63. data/examples/legacy/not_checked/shoes-manual/radio_alternative_1.rb +7 -0
  64. data/examples/legacy/not_checked/shoes-manual/radio_alternative_2.rb +9 -0
  65. data/examples/legacy/not_checked/shoes-manual/rotate_rectangle.rb +6 -0
  66. data/examples/legacy/not_checked/shoes-manual/shape.rb +11 -0
  67. data/examples/legacy/not_checked/shoes-manual/static/avatar.png +0 -0
  68. data/examples/legacy/not_checked/shoes-manual/stroke.rb +5 -0
  69. data/examples/legacy/not_checked/shoes-manual/style.rb +3 -0
  70. data/examples/legacy/not_checked/shoes-manual/style_alternative_1.rb +4 -0
  71. data/examples/legacy/not_checked/shoes-manual/style_alternative_2.rb +5 -0
  72. data/examples/legacy/not_checked/shoes-manual/style_length.rb +5 -0
  73. data/examples/legacy/not_checked/shoes-manual/timer.rb +6 -0
  74. data/examples/legacy/not_checked/shoes-manual/trigger_window.rb +8 -0
  75. data/examples/legacy/not_checked/shoes-manual/window_owner.rb +8 -0
  76. data/examples/legacy/not_checked/simple/anim-shapes.rb +1 -1
  77. data/examples/legacy/not_checked/speedometer_app.rb +55 -0
  78. data/examples/legacy/working/shoes_manual/alert_button.rb +2 -0
  79. data/examples/legacy/working/shoes_manual/animate.rb +7 -0
  80. data/examples/legacy/working/shoes_manual/background_para.rb +4 -0
  81. data/examples/legacy/working/shoes_manual/button_alternative.rb +7 -0
  82. data/examples/legacy/working/shoes_manual/checkbox.rb +17 -0
  83. data/examples/legacy/working/shoes_manual/download.rb +12 -0
  84. data/examples/legacy/working/shoes_manual/edit_box.rb +6 -0
  85. data/examples/legacy/working/shoes_manual/editline.rb +7 -0
  86. data/examples/legacy/working/shoes_manual/fixed_height.rb +8 -0
  87. data/examples/legacy/working/shoes_manual/fixed_width.rb +12 -0
  88. data/examples/legacy/working/shoes_manual/image.rb +5 -0
  89. data/examples/legacy/working/shoes_manual/instance_variable_check.rb +10 -0
  90. data/examples/legacy/working/shoes_manual/message.rb +18 -0
  91. data/examples/legacy/working/shoes_manual/rectangle.rb +6 -0
  92. data/examples/legacy/working/shoes_manual/save_download.rb +12 -0
  93. data/examples/legacy/working/shoes_manual/self_check.rb +10 -0
  94. data/examples/legacy/working/shoes_manual/stack.rb +7 -0
  95. data/examples/legacy/working/shoes_manual/style_info.rb +8 -0
  96. data/examples/legacy/working/shoes_manual/utf8_support.rb +8 -0
  97. data/examples/legacy/working/shoes_manual/width.rb +4 -0
  98. data/examples/legacy/working/simple/image-icon.rb +3 -0
  99. data/examples/legacy/{not_checked → working}/simple/image.rb +1 -1
  100. data/examples/list_box_choose.rb +17 -0
  101. data/examples/local_assets/local_file_server.rb +82 -0
  102. data/examples/local_assets/multi_image.rb +5 -0
  103. data/examples/local_assets/sample.gif +0 -0
  104. data/examples/local_assets/sample.mp4 +0 -0
  105. data/examples/local_assets/small.png +0 -0
  106. data/examples/local_fonts.rb +5 -2
  107. data/examples/local_images.rb +2 -3
  108. data/examples/margin.rb +13 -0
  109. data/examples/margin_check.rb +27 -0
  110. data/examples/oval-with-kwargs.rb +3 -0
  111. data/examples/oval.rb +26 -0
  112. data/examples/para/para_text.rb +14 -0
  113. data/examples/para_font_styles.rb +17 -0
  114. data/examples/para_font_variant.rb +6 -0
  115. data/examples/para_fontweight.rb +13 -0
  116. data/examples/parse_xl_funnies.rb +3 -0
  117. data/examples/progress.rb +31 -0
  118. data/examples/radio/radio_groups.rb +2 -2
  119. data/examples/rect.rb +4 -0
  120. data/examples/rotate_shapes.rb +17 -0
  121. data/examples/scarpe_ext.rb +3 -0
  122. data/examples/shapes/star.rb +1 -3
  123. data/examples/simpler-menu.rb +21 -0
  124. data/examples/spacing.rb +1 -1
  125. data/examples/span.rb +4 -2
  126. data/exe/scarpe +2 -1
  127. data/lacci/Gemfile +2 -0
  128. data/lacci/Gemfile.lock +8 -1
  129. data/lacci/lacci.gemspec +2 -2
  130. data/lacci/lib/lacci/scarpe_cli.rb +2 -2
  131. data/lacci/lib/lacci/scarpe_core.rb +2 -1
  132. data/lacci/lib/lacci/version.rb +1 -1
  133. data/lacci/lib/scarpe/niente/app.rb +23 -0
  134. data/lacci/lib/scarpe/niente/display_service.rb +66 -0
  135. data/lacci/lib/scarpe/niente/drawable.rb +59 -0
  136. data/lacci/lib/scarpe/niente/shoes_spec.rb +93 -0
  137. data/lacci/lib/scarpe/niente.rb +32 -0
  138. data/lacci/lib/shoes/app.rb +111 -72
  139. data/lacci/lib/shoes/background.rb +2 -2
  140. data/lacci/lib/shoes/border.rb +2 -2
  141. data/lacci/lib/shoes/builtins.rb +63 -0
  142. data/lacci/lib/shoes/changelog.rb +52 -0
  143. data/lacci/lib/shoes/colors.rb +3 -1
  144. data/lacci/lib/shoes/constants.rb +41 -2
  145. data/lacci/lib/shoes/display_service.rb +80 -18
  146. data/lacci/lib/shoes/download.rb +2 -2
  147. data/lacci/lib/shoes/drawable.rb +654 -0
  148. data/lacci/lib/shoes/drawables/arc.rb +27 -0
  149. data/lacci/lib/shoes/drawables/arrow.rb +21 -0
  150. data/lacci/lib/shoes/drawables/border.rb +28 -0
  151. data/lacci/lib/shoes/drawables/button.rb +57 -0
  152. data/lacci/lib/shoes/drawables/check.rb +33 -0
  153. data/lacci/lib/shoes/drawables/document_root.rb +20 -0
  154. data/lacci/lib/shoes/{widgets → drawables}/edit_box.rb +9 -8
  155. data/lacci/lib/shoes/{widgets → drawables}/edit_line.rb +8 -7
  156. data/lacci/lib/shoes/drawables/flow.rb +20 -0
  157. data/lacci/lib/shoes/drawables/font_helper.rb +62 -0
  158. data/lacci/lib/shoes/{widgets → drawables}/image.rb +7 -7
  159. data/lacci/lib/shoes/drawables/line.rb +17 -0
  160. data/lacci/lib/shoes/drawables/link.rb +31 -0
  161. data/lacci/lib/shoes/drawables/list_box.rb +59 -0
  162. data/lacci/lib/shoes/drawables/oval.rb +48 -0
  163. data/lacci/lib/shoes/drawables/para.rb +206 -0
  164. data/lacci/lib/shoes/drawables/progress.rb +15 -0
  165. data/lacci/lib/shoes/drawables/radio.rb +35 -0
  166. data/lacci/lib/shoes/drawables/rect.rb +18 -0
  167. data/lacci/lib/shoes/{widgets → drawables}/shape.rb +8 -8
  168. data/lacci/lib/shoes/drawables/slot.rb +178 -0
  169. data/lacci/lib/shoes/drawables/stack.rb +21 -0
  170. data/lacci/lib/shoes/drawables/star.rb +28 -0
  171. data/lacci/lib/shoes/drawables/subscription_item.rb +93 -0
  172. data/lacci/lib/shoes/drawables/text_drawable.rb +122 -0
  173. data/lacci/lib/shoes/drawables/video.rb +17 -0
  174. data/lacci/lib/shoes/drawables/widget.rb +74 -0
  175. data/lacci/lib/shoes/drawables.rb +32 -0
  176. data/lacci/lib/shoes/errors.rb +38 -0
  177. data/lacci/lib/shoes/log.rb +2 -2
  178. data/lacci/lib/shoes/margin_helper.rb +79 -0
  179. data/lacci/lib/shoes/ruby_extensions.rb +15 -0
  180. data/lacci/lib/shoes-spec.rb +93 -0
  181. data/lacci/lib/shoes.rb +31 -10
  182. data/lacci/test/.gitignore +1 -0
  183. data/lacci/test/test_draw_context.rb +167 -0
  184. data/lacci/test/test_font_helper.rb +57 -0
  185. data/lacci/test/test_helper.rb +81 -0
  186. data/lacci/test/test_lacci.rb +99 -3
  187. data/lacci/test/test_margin_helper.rb +82 -0
  188. data/lacci/test/test_niente_test_infra.rb +26 -0
  189. data/lacci/test/test_oval.rb +82 -0
  190. data/lacci/test/test_parenting.rb +140 -0
  191. data/lacci/test/test_shoes_errors.rb +49 -0
  192. data/lacci/test/test_text_drawables.rb +23 -0
  193. data/lib/scarpe/assets.rb +18 -0
  194. data/lib/scarpe/cats_cradle.rb +84 -103
  195. data/lib/scarpe/errors.rb +77 -0
  196. data/lib/scarpe/shoes_spec.rb +160 -0
  197. data/lib/scarpe/version.rb +2 -2
  198. data/lib/scarpe/wv/app.rb +21 -20
  199. data/lib/scarpe/wv/arc.rb +4 -51
  200. data/lib/scarpe/wv/arrow.rb +9 -0
  201. data/lib/scarpe/wv/border.rb +9 -18
  202. data/lib/scarpe/wv/button.rb +7 -35
  203. data/lib/scarpe/wv/check.rb +3 -5
  204. data/lib/scarpe/wv/control_interface.rb +20 -30
  205. data/lib/scarpe/wv/document_root.rb +81 -4
  206. data/lib/scarpe/wv/{widget.rb → drawable.rb} +71 -82
  207. data/lib/scarpe/wv/edit_box.rb +8 -18
  208. data/lib/scarpe/wv/edit_line.rb +9 -20
  209. data/lib/scarpe/wv/flow.rb +2 -18
  210. data/lib/scarpe/wv/image.rb +7 -30
  211. data/lib/scarpe/wv/line.rb +3 -25
  212. data/lib/scarpe/wv/link.rb +6 -17
  213. data/lib/scarpe/wv/list_box.rb +6 -29
  214. data/lib/scarpe/wv/oval.rb +13 -0
  215. data/lib/scarpe/wv/para.rb +12 -30
  216. data/lib/scarpe/wv/progress.rb +19 -0
  217. data/lib/scarpe/wv/radio.rb +9 -10
  218. data/lib/scarpe/wv/rect.rb +13 -0
  219. data/lib/scarpe/wv/scarpe_extensions.rb +8 -0
  220. data/lib/scarpe/wv/shape.rb +13 -13
  221. data/lib/scarpe/wv/slot.rb +8 -25
  222. data/lib/scarpe/wv/stack.rb +2 -18
  223. data/lib/scarpe/wv/star.rb +3 -53
  224. data/lib/scarpe/wv/subscription_item.rb +38 -4
  225. data/lib/scarpe/wv/text_drawable.rb +90 -0
  226. data/lib/scarpe/wv/video.rb +15 -15
  227. data/lib/scarpe/wv/web_wrangler.rb +320 -328
  228. data/lib/scarpe/wv/webview_local_display.rb +52 -33
  229. data/lib/scarpe/wv/webview_relay_display.rb +12 -12
  230. data/lib/scarpe/wv/webview_relay_util.rb +7 -10
  231. data/lib/scarpe/wv/wv_display_worker.rb +2 -2
  232. data/lib/scarpe/wv.rb +52 -12
  233. data/lib/scarpe/wv_local.rb +1 -1
  234. data/lib/scarpe/wv_relay.rb +1 -1
  235. data/lib/scarpe.rb +1 -0
  236. data/logger/debug_web_wrangler.json +1 -1
  237. data/logger/scarpe_wv_test.json +1 -1
  238. data/scarpe-components/Gemfile +4 -1
  239. data/scarpe-components/Gemfile.lock +85 -0
  240. data/scarpe-components/README.md +2 -2
  241. data/scarpe-components/assets/bootstrap-themes/bootstrap-cerulean.css +12229 -0
  242. data/scarpe-components/assets/bootstrap-themes/bootstrap-cosmo.css +11810 -0
  243. data/scarpe-components/assets/bootstrap-themes/bootstrap-cyborg.css +12210 -0
  244. data/scarpe-components/assets/bootstrap-themes/bootstrap-darkly.css +12153 -0
  245. data/scarpe-components/assets/bootstrap-themes/bootstrap-flatly.css +12126 -0
  246. data/scarpe-components/assets/bootstrap-themes/bootstrap-icons.min.css +5 -0
  247. data/scarpe-components/assets/bootstrap-themes/bootstrap-journal.css +12099 -0
  248. data/scarpe-components/assets/bootstrap-themes/bootstrap-litera.css +12211 -0
  249. data/scarpe-components/assets/bootstrap-themes/bootstrap-lumen.css +12369 -0
  250. data/scarpe-components/assets/bootstrap-themes/bootstrap-lux.css +11928 -0
  251. data/scarpe-components/assets/bootstrap-themes/bootstrap-materia.css +13184 -0
  252. data/scarpe-components/assets/bootstrap-themes/bootstrap-minty.css +12177 -0
  253. data/scarpe-components/assets/bootstrap-themes/bootstrap-morph.css +12750 -0
  254. data/scarpe-components/assets/bootstrap-themes/bootstrap-pulse.css +11890 -0
  255. data/scarpe-components/assets/bootstrap-themes/bootstrap-quartz.css +12622 -0
  256. data/scarpe-components/assets/bootstrap-themes/bootstrap-sandstone.css +12201 -0
  257. data/scarpe-components/assets/bootstrap-themes/bootstrap-simplex.css +12186 -0
  258. data/scarpe-components/assets/bootstrap-themes/bootstrap-sketchy.css +12451 -0
  259. data/scarpe-components/assets/bootstrap-themes/bootstrap-slate.css +12492 -0
  260. data/scarpe-components/assets/bootstrap-themes/bootstrap-solar.css +12149 -0
  261. data/scarpe-components/assets/bootstrap-themes/bootstrap-spacelab.css +12266 -0
  262. data/scarpe-components/assets/bootstrap-themes/bootstrap-superhero.css +12216 -0
  263. data/scarpe-components/assets/bootstrap-themes/bootstrap-united.css +12077 -0
  264. data/scarpe-components/assets/bootstrap-themes/bootstrap-vapor.css +12549 -0
  265. data/scarpe-components/assets/bootstrap-themes/bootstrap-yeti.css +12325 -0
  266. data/scarpe-components/assets/bootstrap-themes/bootstrap-zephyr.css +12283 -0
  267. data/scarpe-components/assets/bootstrap-themes/bootstrap.bundle.min.js +7 -0
  268. data/scarpe-components/lib/scarpe/components/asset_server.rb +219 -0
  269. data/scarpe-components/lib/scarpe/components/base64.rb +23 -5
  270. data/scarpe-components/lib/scarpe/components/calzini/alert.rb +49 -0
  271. data/scarpe-components/lib/scarpe/components/calzini/art_drawables.rb +227 -0
  272. data/scarpe-components/lib/scarpe/components/calzini/border.rb +38 -0
  273. data/scarpe-components/lib/scarpe/components/calzini/button.rb +37 -0
  274. data/scarpe-components/lib/scarpe/components/calzini/misc.rb +136 -0
  275. data/scarpe-components/lib/scarpe/components/calzini/para.rb +237 -0
  276. data/scarpe-components/lib/scarpe/components/calzini/slots.rb +109 -0
  277. data/scarpe-components/lib/scarpe/components/calzini.rb +236 -0
  278. data/scarpe-components/lib/scarpe/components/errors.rb +24 -0
  279. data/scarpe-components/lib/scarpe/components/file_helpers.rb +1 -0
  280. data/scarpe-components/lib/scarpe/components/html.rb +134 -0
  281. data/scarpe-components/lib/scarpe/components/minitest_export_reporter.rb +83 -0
  282. data/scarpe-components/lib/scarpe/components/minitest_import_runnable.rb +98 -0
  283. data/scarpe-components/lib/scarpe/components/minitest_result.rb +127 -0
  284. data/scarpe-components/lib/scarpe/components/modular_logger.rb +5 -5
  285. data/scarpe-components/lib/scarpe/components/print_logger.rb +22 -3
  286. data/scarpe-components/lib/scarpe/components/process_helpers.rb +37 -0
  287. data/scarpe-components/lib/scarpe/components/promises.rb +14 -14
  288. data/scarpe-components/lib/scarpe/components/segmented_file_loader.rb +36 -17
  289. data/scarpe-components/lib/scarpe/components/string_helpers.rb +10 -0
  290. data/scarpe-components/lib/scarpe/components/tiranti.rb +167 -0
  291. data/scarpe-components/lib/scarpe/components/unit_test_helpers.rb +48 -6
  292. data/scarpe-components/lib/scarpe/components/version.rb +2 -2
  293. data/scarpe-components/test/assets/big-image.png +0 -0
  294. data/scarpe-components/test/assets/big-stylesheet.css +497 -0
  295. data/scarpe-components/test/assets/little-image.png +0 -0
  296. data/scarpe-components/test/assets/little-stylesheet.css +1 -0
  297. data/scarpe-components/test/calzini/test_calzini_alert.rb +30 -0
  298. data/scarpe-components/test/calzini/test_calzini_art_drawables.rb +105 -0
  299. data/scarpe-components/test/calzini/test_calzini_button.rb +54 -0
  300. data/scarpe-components/test/calzini/test_calzini_misc.rb +115 -0
  301. data/scarpe-components/test/calzini/test_calzini_para.rb +34 -0
  302. data/scarpe-components/test/calzini/test_calzini_slots.rb +85 -0
  303. data/scarpe-components/test/calzini/test_calzini_text_drawables.rb +106 -0
  304. data/scarpe-components/test/calzini/test_various.rb +133 -0
  305. data/scarpe-components/test/mtr_data/exception.json +1 -0
  306. data/scarpe-components/test/mtr_data/fail_with_message.json +1 -0
  307. data/scarpe-components/test/mtr_data/skipped_no_message.json +1 -0
  308. data/scarpe-components/test/mtr_data/skipped_w_msg.json +1 -0
  309. data/scarpe-components/test/mtr_data/succeed_2_asserts.json +1 -0
  310. data/scarpe-components/test/test_asset_server.rb +72 -0
  311. data/scarpe-components/test/test_components.rb +31 -2
  312. data/scarpe-components/test/test_dimensions.rb +26 -0
  313. data/scarpe-components/test/test_helper.rb +20 -1
  314. data/scarpe-components/test/test_html.rb +65 -0
  315. data/scarpe-components/test/test_minitest_result.rb +68 -0
  316. data/scarpe-components/test/test_promises.rb +5 -4
  317. data/scarpe-components/test/test_segmented_app_files.rb +10 -6
  318. data/scarpegen.rb +14 -14
  319. data/sig/scarpe.rbs +1 -1
  320. data/tasks/check_html_fixtures.rb +140 -0
  321. data/tasks/regenerate_html_fixtures.rb +104 -0
  322. data/templates/basic_class_template.erb +13 -14
  323. data/templates/class_template_with_event_bind.erb +4 -4
  324. data/templates/class_template_with_shapes.erb +8 -28
  325. data/templates/example_template.erb +1 -1
  326. data/templates/module_template.erb +4 -4
  327. data/templates/webview_template.erb +3 -2
  328. metadata +286 -80
  329. data/examples/legacy/not_checked/shoes-contrib/elements/image-icon.rb +0 -3
  330. data/lacci/lib/shoes/spacing.rb +0 -9
  331. data/lacci/lib/shoes/widget.rb +0 -218
  332. data/lacci/lib/shoes/widgets/alert.rb +0 -19
  333. data/lacci/lib/shoes/widgets/arc.rb +0 -51
  334. data/lacci/lib/shoes/widgets/button.rb +0 -35
  335. data/lacci/lib/shoes/widgets/check.rb +0 -28
  336. data/lacci/lib/shoes/widgets/document_root.rb +0 -20
  337. data/lacci/lib/shoes/widgets/flow.rb +0 -22
  338. data/lacci/lib/shoes/widgets/font.rb +0 -14
  339. data/lacci/lib/shoes/widgets/line.rb +0 -18
  340. data/lacci/lib/shoes/widgets/link.rb +0 -25
  341. data/lacci/lib/shoes/widgets/list_box.rb +0 -25
  342. data/lacci/lib/shoes/widgets/para.rb +0 -68
  343. data/lacci/lib/shoes/widgets/radio.rb +0 -35
  344. data/lacci/lib/shoes/widgets/slot.rb +0 -75
  345. data/lacci/lib/shoes/widgets/span.rb +0 -26
  346. data/lacci/lib/shoes/widgets/stack.rb +0 -24
  347. data/lacci/lib/shoes/widgets/star.rb +0 -44
  348. data/lacci/lib/shoes/widgets/subscription_item.rb +0 -60
  349. data/lacci/lib/shoes/widgets/text_widget.rb +0 -51
  350. data/lacci/lib/shoes/widgets/video.rb +0 -15
  351. data/lacci/lib/shoes/widgets.rb +0 -29
  352. data/lib/scarpe/evented_assertions.rb +0 -88
  353. data/lib/scarpe/wv/alert.rb +0 -66
  354. data/lib/scarpe/wv/background.rb +0 -27
  355. data/lib/scarpe/wv/control_interface_test.rb +0 -238
  356. data/lib/scarpe/wv/dimensions.rb +0 -22
  357. data/lib/scarpe/wv/font.rb +0 -36
  358. data/lib/scarpe/wv/html.rb +0 -108
  359. data/lib/scarpe/wv/spacing.rb +0 -41
  360. data/lib/scarpe/wv/span.rb +0 -68
  361. data/lib/scarpe/wv/text_widget.rb +0 -30
  362. /data/examples/legacy/not_checked/{expert → shoes-contrib/basic}/definr.rb +0 -0
  363. /data/examples/legacy/not_checked/{expert → shoes-contrib/basic}/funnies.rb +0 -0
  364. /data/examples/legacy/not_checked/shoes-contrib/{elements → basic}/list_box-select-class.rb +0 -0
  365. /data/examples/legacy/{not_checked → working}/shoes3-tests/editline/editline.rb +0 -0
  366. /data/examples/legacy/{not_checked/shoes-contrib/basic → working/simple}/basic-edit-box.rb +0 -0
  367. /data/examples/legacy/{not_checked/shoes-contrib/elements → working/simple}/basic-fps.rb +0 -0
  368. /data/examples/legacy/{not_checked/shoes-contrib/elements → working/simple}/border-cat.rb +0 -0
  369. /data/examples/legacy/{not_checked/shoes-contrib/elements → working/simple}/check-mate.rb +0 -0
  370. /data/examples/legacy/{not_checked/shoes-contrib/manipulation → working/simple}/clear-slot.rb +0 -0
  371. /data/examples/legacy/{not_checked/shoes-contrib/basic → working/simple}/clock.rb +0 -0
  372. /data/examples/legacy/{not_checked/shoes-contrib/basic → working/simple}/gradient-shoes.rb +0 -0
  373. /data/examples/legacy/{not_checked/shoes-contrib/basic → working/simple}/list_box-shape-report.rb +0 -0
  374. /data/examples/legacy/{not_checked/shoes-contrib/elements → working/simple}/list_box.rb +0 -0
  375. /data/examples/legacy/{not_checked/shoes-contrib/elements → working/simple}/phat-button.rb +0 -0
  376. /data/examples/legacy/{not_checked/shoes-contrib → working}/simple/simple-calc.rb +0 -0
  377. /data/examples/legacy/{not_checked/shoes-contrib/position → working/simple}/stack-width.rb +0 -0
  378. /data/examples/legacy/{not_checked/shoes-contrib/elements → working/simple}/width-introspec.rb +0 -0
@@ -0,0 +1,127 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "minitest"
4
+ require "json"
5
+ #require "json/add/exception"
6
+
7
+ module Scarpe; module Components; end; end
8
+
9
+ # A MinitestResult imports a JSON file from a minitest_export_reporter.
10
+ # But instead of creating a Minitest::Test to report the result, the
11
+ # MinitestResult is just a queryable Ruby object.
12
+ #
13
+ # MinitestResult assumes there will be only one class and one method
14
+ # in the JSON, which is true for Scarpe but not necessarily in general.
15
+ class Scarpe::Components::MinitestResult
16
+ attr_reader :assertions
17
+ attr_reader :method_name
18
+ attr_reader :class_name
19
+
20
+ def initialize(filename)
21
+ data = JSON.parse File.read(filename)
22
+
23
+ unless data.size == 1
24
+ # We would want a different interface to support this in general. For now we don't
25
+ # need it to work in general.
26
+ raise "Scarpe::Components::MinitestResult only supports one class and method in results!"
27
+ end
28
+
29
+ item = data.first
30
+
31
+ @assertions = item["assertions"]
32
+ @method_name = item["name"]
33
+ @class_name = item["klass"]
34
+ @time = item["time"]
35
+ @metadata = item.key?("metadata") ? item["metadata"]: {}
36
+
37
+ @skip = false
38
+ @exceptions = []
39
+ @failures = []
40
+ item["failures"].each do |f|
41
+ # JSON.parse ignores json_class and won't create an arbitrary object. That's good
42
+ # because Minitest::UnexpectedError seems to load in a bad way, so we don't want
43
+ # it to auto-instantiate.
44
+ d = JSON.parse f[1]
45
+ msg = d["m"]
46
+ case d["json_class"]
47
+ when "Minitest::UnexpectedError"
48
+ @exceptions << msg
49
+ when "Minitest::Skip"
50
+ @skip = msg
51
+ when "Minitest::Assertion"
52
+ @failures << msg
53
+ else
54
+ raise Scarpe::InternalError, "Didn't expect type #{t.inspect} as exception type when importing Minitest tests!"
55
+ end
56
+ end
57
+ end
58
+
59
+ def one_word_result
60
+ return "error" if self.error?
61
+ return "fail" if self.fail?
62
+ return "skip" if self.skip?
63
+ "success"
64
+ end
65
+
66
+ def result_and_message
67
+ return ["error", error_message] if self.error?
68
+ return ["fail", fail_message] if self.fail?
69
+ return ["skip", skip_message] if self.skip?
70
+ ["success", "OK"]
71
+ end
72
+
73
+ def console_summary
74
+ return "Error(s): #{@exceptions.inspect}" if self.error?
75
+ return "Failure: #{@failures.inspect}" if self.fail?
76
+ return "Skip: #{skip_message.inspect}" if self.skip?
77
+ "Success!"
78
+ end
79
+
80
+ def check(expect_result: :success, min_asserts: nil, max_asserts: nil)
81
+ unless [:error, :fail, :skip, :success].include?(expect_result)
82
+ raise Scarpe::InternalError, "Expected test result should be one of [:success, :fail, :error, :skip]!"
83
+ end
84
+
85
+ res, msg = result_and_message
86
+ if expect_result.to_s != res
87
+ return [false, "Expected #{expect_result} but got #{res}: #{msg}!"]
88
+ end
89
+
90
+ if min_asserts && @assertions < min_asserts
91
+ return [false, "Expected success with at least #{min_asserts} assertions but found only #{@assertions}!"]
92
+ end
93
+ if max_asserts && @assertions > max_asserts
94
+ return [false, "Expected success with no more than #{max_asserts} assertions but found only #{@assertions}!"]
95
+ end
96
+
97
+ [true, ""]
98
+ end
99
+
100
+ def error?
101
+ !@exceptions.empty?
102
+ end
103
+
104
+ def fail?
105
+ !@failures.empty?
106
+ end
107
+
108
+ def skip?
109
+ @skip ? true : false
110
+ end
111
+
112
+ def passed?
113
+ @exceptions.empty? && @failures.empty? && !@skip
114
+ end
115
+
116
+ def error_message
117
+ @exceptions[0]
118
+ end
119
+
120
+ def fail_message
121
+ @failures[0]
122
+ end
123
+
124
+ def skip_message
125
+ @skip
126
+ end
127
+ end
@@ -7,9 +7,9 @@ require "shoes/log"
7
7
 
8
8
  # Requires the logging gem
9
9
 
10
- class Scarpe; end
10
+ module Scarpe; end
11
11
  module Scarpe::Components; end
12
- class Scarpe
12
+ module Scarpe
13
13
  class Components::ModularLogImpl
14
14
  include Shoes::Log # for constants
15
15
 
@@ -32,7 +32,7 @@ class Scarpe
32
32
  when "fatal"
33
33
  :fatal
34
34
  else
35
- raise "Don't know how to treat #{data.inspect} as a logger severity!"
35
+ raise Shoes::Errors::InvalidAttributeValueError, "Don't know how to treat #{data.inspect} as a logger severity!"
36
36
  end
37
37
  end
38
38
 
@@ -45,7 +45,7 @@ class Scarpe
45
45
  when String
46
46
  Logging.appenders.file data, layout: @custom_log_layout
47
47
  else
48
- raise "Don't know how to convert #{data.inspect} to an appender!"
48
+ raise Shoes::Errors::InvalidAttributeValueError, "Don't know how to convert #{data.inspect} to an appender!"
49
49
  end
50
50
  end
51
51
 
@@ -64,7 +64,7 @@ class Scarpe
64
64
 
65
65
  logger.level = name_to_severity(level)
66
66
  else
67
- raise "Don't know how to use #{data.inspect} to specify a logger!"
67
+ raise Shoes::Errors::InvalidAttributeValueError, "Don't know how to use #{data.inspect} to specify a logger!"
68
68
  end
69
69
  end
70
70
 
@@ -3,29 +3,48 @@
3
3
  require "shoes/log"
4
4
  require "json"
5
5
 
6
- class Scarpe; end
6
+ module Scarpe; end
7
7
  module Scarpe::Components; end
8
8
  class Scarpe::Components::PrintLogImpl
9
9
  include Shoes::Log # for constants
10
10
 
11
11
  class PrintLogger
12
+ class << self
13
+ attr_accessor :silence
14
+ attr_accessor :min_level
15
+ end
16
+
17
+ LEVELS = {
18
+ :never => 1000,
19
+ :error => 4,
20
+ :warn => 3,
21
+ :info => 2,
22
+ :debug => 1,
23
+ :always => -1,
24
+ }
25
+ PrintLogger.min_level = LEVELS[:always]
26
+
12
27
  def initialize(component_name)
13
28
  @comp_name = component_name
14
29
  end
15
30
 
16
31
  def error(msg)
32
+ return if PrintLogger.silence || PrintLogger.min_level > LEVELS[:error]
17
33
  puts "#{@comp_name} error: #{msg}"
18
34
  end
19
35
 
20
36
  def warn(msg)
21
- puts "#{@comp_name} warn: #{msg}"
37
+ return if PrintLogger.silence || PrintLogger.min_level > LEVELS[:warn]
38
+ puts "#{@comp_name} warn: #{msg}" unless PrintLogger.silence
22
39
  end
23
40
 
24
41
  def debug(msg)
25
- puts "#{@comp_name} debug: #{msg}"
42
+ return if PrintLogger.silence || PrintLogger.min_level > LEVELS[:debug]
43
+ puts "#{@comp_name} debug: #{msg}" unless PrintLogger.silence
26
44
  end
27
45
 
28
46
  def info(msg)
47
+ return if PrintLogger.silence || PrintLogger.min_level > LEVELS[:info]
29
48
  puts "#{@comp_name} info: #{msg}"
30
49
  end
31
50
  end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ # These can be used for unit tests, but also more generally.
4
+
5
+ require_relative "file_helpers"
6
+
7
+ module Scarpe::Components::ProcessHelpers
8
+ include Scarpe::Components::FileHelpers
9
+
10
+ # Run the command and capture its stdout and stderr output, and whether
11
+ # it succeeded or failed. Return after the command has completed.
12
+ # The awkward name is because this is normally a component of another
13
+ # library. Ordinarily you'd want to raise a library-specific exception
14
+ # on failure, print a library-specific message or delimiter, or otherwise
15
+ # handle success and failure. This is too general as-is.
16
+ #
17
+ # @param cmd [String,Array<String>] the command to run in Kernel#spawn format
18
+ # @return [Array(String,String,bool)] the stdout output, stderr output and success/failure of the command in a 3-element Array
19
+ def run_out_err_result(cmd)
20
+ out_str = ""
21
+ err_str = ""
22
+ success = nil
23
+
24
+ with_tempfiles([
25
+ ["scarpe_cmd_stdout", ""],
26
+ ["scarpe_cmd_stderr", ""],
27
+ ]) do |stdout_file, stderr_file|
28
+ pid = Kernel.spawn(cmd, out: stdout_file, err: stderr_file)
29
+ Process.wait(pid)
30
+ success = $?.success?
31
+ out_str = File.read stdout_file
32
+ err_str = File.read stderr_file
33
+ end
34
+
35
+ [out_str, err_str, success]
36
+ end
37
+ end
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class Scarpe; end
3
+ module Scarpe; end
4
4
  module Scarpe::Components; end
5
- class Scarpe
5
+ module Scarpe
6
6
  # Scarpe::Promise is a promises library, but one with no form of built-in
7
7
  # concurrency. Instead, promise callbacks are executed synchronously.
8
8
  # Even execution is usually synchronous, but can also be handled manually
@@ -198,7 +198,7 @@ class Scarpe
198
198
  case @state
199
199
  when :fulfilled
200
200
  # Should this be a no-op instead?
201
- raise "Registering an executor on an already fulfilled promise means it will never run!"
201
+ raise Scarpe::NoOperationError, "Registering an executor on an already fulfilled promise means it will never run!"
202
202
  when :rejected
203
203
  return
204
204
  when :unscheduled
@@ -207,7 +207,7 @@ class Scarpe
207
207
  @executor = block
208
208
  call_executor
209
209
  else
210
- raise "Internal error, illegal state!"
210
+ raise Scarpe::InternalError, "Internal error, illegal state!"
211
211
  end
212
212
 
213
213
  self
@@ -222,16 +222,16 @@ class Scarpe
222
222
 
223
223
  # First, filter out illegal input
224
224
  unless PROMISE_STATES.include?(old_state)
225
- raise "Internal Promise error! Internal state was #{old_state.inspect}! Legal states: #{PROMISE_STATES.inspect}"
225
+ raise Scarpe::InternalError, "Internal Promise error! Internal state was #{old_state.inspect}! Legal states: #{PROMISE_STATES.inspect}"
226
226
  end
227
227
 
228
228
  unless PROMISE_STATES.include?(new_state)
229
- raise "Internal Promise error! Internal state was set to #{new_state.inspect}! " +
229
+ raise Scarpe::InternalError, "Internal Promise error! Internal state was set to #{new_state.inspect}! " +
230
230
  "Legal states: #{PROMISE_STATES.inspect}"
231
231
  end
232
232
 
233
233
  if new_state != :fulfilled && new_state != :rejected && !value_or_reason.nil?
234
- raise "Internal promise error! Non-completed state transitions should not specify a value or reason!"
234
+ raise Scarpe::InternalError, "Internal promise error! Non-completed state transitions should not specify a value or reason!"
235
235
  end
236
236
 
237
237
  # Here's our state-transition grid for what we're doing here.
@@ -254,11 +254,11 @@ class Scarpe
254
254
 
255
255
  # Transitioning to any *different* state after being fulfilled or rejected? Nope. Those states are final.
256
256
  if complete?
257
- raise "Internal Promise error! Trying to change state from #{old_state.inspect} to #{new_state.inspect}!"
257
+ raise Scarpe::InternalError, "Internal Promise error! Trying to change state from #{old_state.inspect} to #{new_state.inspect}!"
258
258
  end
259
259
 
260
260
  if old_state == :pending && new_state == :unscheduled
261
- raise "Can't change state from :pending to :unscheduled! Scheduling is not reversible!"
261
+ raise Shoes::Errors::InvalidAttributeValueError, "Can't change state from :pending to :unscheduled! Scheduling is not reversible!"
262
262
  end
263
263
 
264
264
  # The next three checks should all be followed by calling handlers for the newly-changed state.
@@ -341,7 +341,7 @@ class Scarpe
341
341
  @on_scheduled.each { |h| h.call(*@parents.map(&:returned_value)) }
342
342
  @on_scheduled = []
343
343
  else
344
- raise "Internal error! Trying to call handlers for #{state.inspect}!"
344
+ raise Scarpe::InternalError, "Internal error! Trying to call handlers for #{state.inspect}!"
345
345
  end
346
346
  end
347
347
 
@@ -367,7 +367,7 @@ class Scarpe
367
367
  end
368
368
 
369
369
  def call_executor
370
- raise("Internal error! Should not call_executor with no executor!") unless @executor
370
+ raise(Scarpe::InternalError, "Internal error! Should not call_executor with no executor!") unless @executor
371
371
 
372
372
  begin
373
373
  result = @executor.call(*@parents.map(&:returned_value))
@@ -389,7 +389,7 @@ class Scarpe
389
389
  # @return [Scarpe::Promise] self
390
390
  def on_fulfilled(&handler)
391
391
  unless handler
392
- raise "You must pass a block to on_fulfilled!"
392
+ raise Shoes::Errors::InvalidAttributeValueError, "You must pass a block to on_fulfilled!"
393
393
  end
394
394
 
395
395
  case @state
@@ -411,7 +411,7 @@ class Scarpe
411
411
  # @return [Scarpe::Promise] self
412
412
  def on_rejected(&handler)
413
413
  unless handler
414
- raise "You must pass a block to on_rejected!"
414
+ raise Shoes::Errors::InvalidAttributeValueError, "You must pass a block to on_rejected!"
415
415
  end
416
416
 
417
417
  case @state
@@ -434,7 +434,7 @@ class Scarpe
434
434
  # @return [Scarpe::Promise] self
435
435
  def on_scheduled(&handler)
436
436
  unless handler
437
- raise "You must pass a block to on_scheduled!"
437
+ raise Shoes::Errors::InvalidAttributeValueError, "You must pass a block to on_scheduled!"
438
438
  end
439
439
 
440
440
  # Add a pending handler or call it now
@@ -14,7 +14,7 @@ module Scarpe::Components
14
14
  # @return <void>
15
15
  def add_segment_type(type, handler)
16
16
  if segment_type_hash.key?(type)
17
- raise "Segment type #{type.inspect} already exists!"
17
+ raise Shoes::Errors::InvalidAttributeValueError, "Segment type #{type.inspect} already exists!"
18
18
  end
19
19
 
20
20
  segment_type_hash[type] = handler
@@ -22,11 +22,23 @@ module Scarpe::Components
22
22
 
23
23
  # Return an Array of segment type labels, such as "code" and "app_test".
24
24
  #
25
- # @return Array<String> the segment type labels
25
+ # @return [Array<String>] the segment type labels
26
26
  def segment_types
27
27
  segment_type_hash.keys
28
28
  end
29
29
 
30
+ # Normally a Shoes application will want to keep the default segment types,
31
+ # which allow loading a Shoes app and running a test inside. But sometimes
32
+ # the default handler will be wrong and a library will want to register
33
+ # its own "shoes" and "app_test" segment handlers, or not have any at all.
34
+ # For those applications, it makes sense to clear all segment types before
35
+ # registering its own.
36
+ #
37
+ # @return <void>
38
+ def remove_all_segment_types!
39
+ @segment_type_hash = {}
40
+ end
41
+
30
42
  # Load a .sca file with an optional YAML frontmatter prefix and
31
43
  # multiple file sections which can be treated differently.
32
44
  #
@@ -38,7 +50,7 @@ module Scarpe::Components
38
50
  # @param path [String] the file or directory to treat as a Scarpe app
39
51
  # @return [Boolean] return true if the file is loaded as a segmented Scarpe app file
40
52
  def call(path)
41
- return false unless path.end_with?(".scas")
53
+ return false unless path.end_with?(".scas") || path.end_with?(".sspec")
42
54
 
43
55
  file_load(path)
44
56
  true
@@ -55,14 +67,12 @@ module Scarpe::Components
55
67
  @after_load << block
56
68
  end
57
69
 
58
- private
59
-
60
- def gen_name(segmap)
70
+ def self.gen_name(segmap)
61
71
  ctr = (1..10_000).detect { |i| !segmap.key?("%5d" % i) }
62
72
  "%5d" % ctr
63
73
  end
64
74
 
65
- def tokenize_segments(contents)
75
+ def self.front_matter_and_segments_from_file(contents)
66
76
  require "yaml" # Only load when needed
67
77
  require "English"
68
78
 
@@ -90,12 +100,16 @@ module Scarpe::Components
90
100
  segments.each do |segment|
91
101
  if segment =~ /\A-* +(.*?)\n/
92
102
  # named segment with separator
93
- segmap[::Regexp.last_match(1)] = ::Regexp.last_match.post_match
103
+ name = ::Regexp.last_match(1)
104
+
105
+ raise("Duplicate segment name: #{name.inspect}!") if segmap.key?(name)
106
+
107
+ segmap[name] = ::Regexp.last_match.post_match
94
108
  elsif segment =~ /\A-* *\n/
95
109
  # unnamed segment with separator
96
110
  segmap[gen_name(segmap)] = ::Regexp.last_match.post_match
97
111
  else
98
- raise "Internal error when parsing segments in segmented app file! seg: #{segment.inspect}"
112
+ raise Scarpe::InternalError, "Internal error when parsing segments in segmented app file! seg: #{segment.inspect}"
99
113
  end
100
114
  end
101
115
 
@@ -105,19 +119,19 @@ module Scarpe::Components
105
119
  def file_load(path)
106
120
  contents = File.read(path)
107
121
 
108
- front_matter, segmap = tokenize_segments(contents)
122
+ front_matter, segmap = self.class.front_matter_and_segments_from_file(contents)
109
123
 
110
124
  if segmap.empty?
111
- raise "Illegal segmented Scarpe file: must have at least one code segment, not just front matter!"
125
+ raise Scarpe::FileContentError, "Illegal segmented Scarpe file: must have at least one code segment, not just front matter!"
112
126
  end
113
127
 
114
128
  if front_matter[:segments]
115
129
  if front_matter[:segments].size != segmap.size
116
- raise "Number of front matter :segments must equal number of file segments!"
130
+ raise Scarpe::FileContentError, "Number of front matter :segments must equal number of file segments!"
117
131
  end
118
132
  else
119
133
  if segmap.size > 2
120
- raise "Segmented files with more than two segments have to specify what they're for!"
134
+ raise Scarpe::FileContentError, "Segmented files with more than two segments have to specify what they're for!"
121
135
  end
122
136
 
123
137
  # Set to default of shoes code only or shoes code and app test code.
@@ -132,7 +146,7 @@ module Scarpe::Components
132
146
  tf_specs = []
133
147
  front_matter[:segments].each.with_index do |seg_type, idx|
134
148
  unless sth.key?(seg_type)
135
- raise "Unrecognized segment type #{seg_type.inspect}! No matching segment type available!"
149
+ raise Scarpe::FileContentError, "Unrecognized segment type #{seg_type.inspect}! No matching segment type available!"
136
150
  end
137
151
 
138
152
  tf_specs << ["scarpe_#{seg_type}_segment_contents", sv[idx]]
@@ -147,18 +161,23 @@ module Scarpe::Components
147
161
  # Need to call @after_load hooks while tempfiles still exist
148
162
  if @after_load && !@after_load.empty?
149
163
  @after_load.each(&:call)
164
+ @after_load = []
150
165
  end
151
166
  end
152
167
  end
153
168
 
154
169
  # The hash of segment type labels mapped to handlers which will be called.
155
- # Normal client code shouldn't ever call this.
170
+ # This could be called by a display service, a test framework or similar
171
+ # code that wants to define a non-Scarpe-standard file format.
156
172
  #
157
- # @return Hash<String, Object> the name/handler pairs
173
+ # @return [Hash<String, Object>] the name/handler pairs
158
174
  def segment_type_hash
159
175
  @segment_handlers ||= {
160
176
  "shoes" => proc { |seg_file| after_load { load seg_file } },
161
- "app_test" => proc { |seg_file| ENV["SCARPE_APP_TEST"] = seg_file },
177
+ "app_test" => proc do |seg_file|
178
+ ENV["SHOES_SPEC_TEST"] = seg_file
179
+ ENV["SHOES_MINITEST_EXPORT_FILE"] ||= "sspec.json"
180
+ end,
162
181
  }
163
182
  end
164
183
  end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Scarpe; module Components; end; end
4
+ module Scarpe::Components::StringHelpers
5
+ # Cut down from Rails camelize
6
+ def self.camelize(string)
7
+ string = string.sub(/^[a-z\d]*/, &:capitalize)
8
+ string.gsub(/(?:_|(\/))([a-z\d]*)/) { "#{::Regexp.last_match(1)}#{::Regexp.last_match(2).capitalize}" }
9
+ end
10
+ end
@@ -0,0 +1,167 @@
1
+ # frozen_string_literal: true
2
+
3
+ # In Italian, tiranti are bootstraps -- the literal pull-on-a-boot kind, not a step to something better.
4
+ # Tiranti.rb builds on calzini.rb, but renders a Bootstrap-decorated version of the HTML output.
5
+ # You can set Tiranti as your HTML renderer and you'll get Bootstrap versions of all the drawables.
6
+ # Tiranti requires Calzini's files because it falls back to Calzini for a lot of its rendering.
7
+
8
+ require "scarpe/components/calzini"
9
+
10
+ # The Tiranti module expects to be included by a class defining
11
+ # the following methods:
12
+ #
13
+ # * html_id - the HTML ID for the specific rendered DOM object
14
+ # * handler_js_code(event_name) - the JS handler code for this DOM object and event name
15
+ # * (optional) display_properties - the display properties for this object, unless overridden in render()
16
+ module Scarpe::Components::Tiranti
17
+ include Scarpe::Components::Calzini
18
+ extend self
19
+
20
+ # Currently we're using Bootswatch 5.
21
+ # Bootswatch themes downloaded from https://bootswatch.com/5/THEME_NAME/bootstrap.css
22
+
23
+ def empty_page_element(theme: ENV["SCARPE_BOOTSTRAP_THEME"] || "sketchy")
24
+ comp_dir = File.expand_path("#{__dir__}/../../..")
25
+ bootstrap_js_url = Scarpe::Webview.asset_server.asset_url("#{comp_dir}/assets/bootstrap-themes/bootstrap.bundle.min.js", url_type: :asset)
26
+ theme_url = Scarpe::Webview.asset_server.asset_url("#{comp_dir}/assets/bootstrap-themes/bootstrap-#{theme}.css", url_type: :asset)
27
+ icons_url = Scarpe::Webview.asset_server.asset_url("#{comp_dir}/assets/bootstrap-themes/bootstrap-icons.min.css", url_type: :asset)
28
+
29
+ <<~HTML
30
+ <html>
31
+ <head id='head-wvroot'>
32
+ <meta charset="utf-8">
33
+ <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
34
+ <link rel="stylesheet" href=#{theme_url.inspect}>
35
+ <link rel="stylesheet" href=#{icons_url.inspect}>
36
+ <style id='style-wvroot'>
37
+ /** Style resets **/
38
+ body {
39
+ height: 100%;
40
+ overflow: hidden;
41
+ }
42
+ </style>
43
+ </head>
44
+ <body id='body-wvroot'>
45
+ <div id='wrapper-wvroot'></div>
46
+
47
+ <script src=#{bootstrap_js_url}></script>
48
+ </body>
49
+ </html>
50
+ HTML
51
+ end
52
+
53
+ # How do we want to handle theme-specific colours and primary/secondary buttons in Bootstrap?
54
+ # "Disabled" could be checked in properties. Is there any way we can/should use "outline" buttons?
55
+ def button_element(props)
56
+ HTML.render do |h|
57
+ h.button(
58
+ id: html_id,
59
+ type: "button",
60
+ class: props["html_class"] ? "btn #{props["html_class"]}" : "btn btn-primary",
61
+ onclick: handler_js_code("click"), style: button_style(props)
62
+ ) do
63
+ props["text"]
64
+ end
65
+ end
66
+ end
67
+
68
+ private
69
+
70
+ def button_style(props)
71
+ styles = drawable_style(props)
72
+
73
+ styles[:"background-color"] = props["color"] if props["color"]
74
+ styles[:"padding-top"] = props["padding_top"] if props["padding_top"]
75
+ styles[:"padding-bottom"] = props["padding_bottom"] if props["padding_bottom"]
76
+ styles[:color] = props["text_color"] if props["text_color"]
77
+
78
+ # How do we want to handle font size?
79
+ styles[:"font-size"] = props["font_size"] if props["font_size"]
80
+ styles[:"font-size"] = dimensions_length(text_size(props["size"])) if props["size"]
81
+
82
+ styles[:"font-family"] = props["font"] if props["font"]
83
+
84
+ styles
85
+ end
86
+
87
+ public
88
+
89
+ def alert_element(props)
90
+ onclick = handler_js_code(props["event_name"] || "click")
91
+
92
+ HTML.render do |h|
93
+ h.div(id: html_id, class: "modal", tabindex: -1, role: "dialog", style: alert_overlay_style(props)) do
94
+ h.div(class: "modal-dialog", role: "document") do
95
+ h.div(class: "modal-content", style: alert_modal_style) do
96
+ h.div(class: "modal-header") do
97
+ h.h5(class: "modal-title") { "Alert" }
98
+ h.button(type: "button", class: "close", data_dismiss: "modal", aria_label: "Close") do
99
+ h.span(aria_hidden: "true") { "&times;" }
100
+ end
101
+ end
102
+ h.div(class: "modal-body") do
103
+ h.p { props["text"] }
104
+ end
105
+ h.div(class: "modal-footer") do
106
+ h.button(type: "button", onclick:, class: "btn btn-primary") { "OK" }
107
+ #h.button(type: "button", class: "btn btn-secondary") { "Close" }
108
+ end
109
+ end
110
+ end
111
+ end
112
+ end
113
+ end
114
+
115
+ def check_element(props)
116
+ HTML.render do |h|
117
+ h.div class: "form-check" do
118
+ h.input type: :checkbox,
119
+ id: html_id,
120
+ class: "form-check-input",
121
+ onclick: handler_js_code("click"),
122
+ value: props["text"],
123
+ checked: props["checked"],
124
+ style: drawable_style(props)
125
+ end
126
+ end
127
+ end
128
+
129
+ def progress_element(props)
130
+ progress_style = drawable_style(props).merge({
131
+ width: "90%",
132
+ })
133
+ HTML.render do |h|
134
+ h.div(id: html_id, class: "progress", style: progress_style) do
135
+ pct = "%.1f" % ((props["fraction"] || 0.0) * 100.0)
136
+ h.div(
137
+ class: "progress-bar progress-bar-striped progress-bar-animated",
138
+ role: "progressbar",
139
+ "aria-valuenow": pct,
140
+ "aria-valuemin": 0,
141
+ "aria-valuemax": 100,
142
+ style: "width: #{pct}%",
143
+ )
144
+ end
145
+ end
146
+ end
147
+
148
+ def para_element(props, &block)
149
+ ps, _extra = para_style(props)
150
+ size = ps[:"font-size"] || "12px"
151
+ size_int = size.to_i # Mostly useful if it's something like "12px"
152
+ if size.include?("calc") || size.end_with?("%")
153
+ # Very big text!
154
+ props["tag"] = "h2"
155
+ elsif size_int >= 48
156
+ props["tag"] = "h1"
157
+ elsif size_int >= 34
158
+ props["tag"] = "h2"
159
+ elsif size_int >= 26
160
+ props["tag"] = "h3"
161
+ else
162
+ props["tag"] = "p"
163
+ end
164
+
165
+ super
166
+ end
167
+ end