type_station 0.4.7 → 0.5.1

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 (267) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/type_station/editables/admin_bar.js.coffee +2 -0
  3. data/lib/type_station/version.rb +2 -2
  4. data/spec/dummy/log/development.log +403 -0
  5. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/-1/-10rQme50p6Wweb3Wq6CrJWl6V6adB8FUd-QGx37n-Y.cache +1 -0
  6. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/-E/-EnK7iHIgtrb6US5s9rqFOOp7Xe30iBs8b8TVubIWO8.cache +0 -0
  7. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/-_/-_vP4UrvVxIRNll7qrd5MMD6fVyIoqLiVWFJPJQxT-k.cache +1 -0
  8. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/-d/-dFcvM4RhMIQSz7CYdi0GDXPHyVCoxHFJRGr5W4r9EY.cache +1 -0
  9. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/-x/-Xfzrb5ZpAgU7nq8xMib9ad1o3oOuOE25Vo4aII5fb4.cache +1 -0
  10. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/-x/-xVryxrtaDdzxDYNjnC4VmQB9g6g5b1NvjTz9mMa-io.cache +0 -0
  11. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/06/06dJumVHqstRhdIeTOqyATaRHdBGujn7s6nOXweTvN0.cache +1 -0
  12. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/0X/0XEtcbBJIfbhytXfuesQektnrA0CwdWRLDAC-iVmwss.cache +0 -0
  13. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/0_/0_szgaMxxOSt83yeibDRDbvtc3YKgf89jF3ksplGmGs.cache +0 -0
  14. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/0g/0gnIJzElqH6mTZ2BkYWSQ_L7bkhOl3pNpFEeU1l3Pdk.cache +1 -0
  15. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/1B/1BRaQZ9YrnzELpmWduuFBUoY5eGH4Q6yI-l1-YfoYLk.cache +1 -0
  16. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/1C/1CNztfUU44hV3JDVFULBbBPDhs30n2cr7mpAq3ObPV4.cache +2 -0
  17. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/1F/1FW3JoQWdW7lBwY0JY2fn8UuYycxSGptLf1deCT3uU8.cache +1 -0
  18. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/21/21Gr6eOJ8GXD790upLual16rQqQnI_4lH5dbsIy1ufk.cache +1 -0
  19. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/2K/2Km33P_YXYBOTwzlcImlHFNz9t5-o_Vw4Mq1SFLm_8Q.cache +1 -0
  20. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/2u/2ublvlfkT634ytTQmjIYBwtnC0rhivD1ketIrrQ6CU8.cache +1 -0
  21. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/32/320BromjZqZdZ7wyjOmVVo18t52xt4JpAXNURQYa0jw.cache +3 -0
  22. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/3J/3JcRTve3gt1KOnGy3p2PmZkMgmD6Fua5oCvuiofReOc.cache +5 -0
  23. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/3T/3T7Re1TRKeatfec64qlG3QkOkww7JaeR8hIfbJFu5mc.cache +1 -0
  24. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/3_/3_ImLijvfNRP8So1cLL4cy7JadLPUbiHFJdmn_5NjJc.cache +1 -0
  25. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/3k/3kBBxXro4BowZhaPIwPc3zV3q45-0dWVFsP2_X8WZ2U.cache +1 -0
  26. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/3l/3lGXO34nSiCirzB8LWIaPeeRvP4P8IyP7JzdhUI9A4U.cache +1 -0
  27. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/4d/4dUNLfIQ0DKP3Wvb1nbw4uDuMOwOCqRJ_DCE_r-Jh3o.cache +3 -0
  28. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/4j/4jrlN6WljXx-hRZscgz9YAzRk2w4MPUTCmwSDDy0AzQ.cache +5 -0
  29. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/4k/4kQbacDL0TNocHDAw13KxFkQ_DSjwY6jKPGrdoJWlk8.cache +0 -0
  30. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/4u/4u_VmkqsowTVo9LQoexdUHBUVm9GwcnZLBZbtzCh2Yo.cache +1 -0
  31. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/57/574hwjRz-ekbl1ZH5_R-oqPkevbZR4h3Et_ImyVKuJo.cache +1 -0
  32. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/5M/5MPskXp3t9FXleqjoNo4_EJvNjLIIpu7F7cHyNkgDNU.cache +0 -0
  33. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/5Z/5Z9bweNefjqm4beRWuRMP_xmZnJ_USwS7Pw0Uz0FoJM.cache +3 -0
  34. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/5q/5qHrWnJz5DtepM21QDxfHhyDK0N4WXhlU8W0yyb7m4w.cache +0 -0
  35. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/6-/6-FoMmlvvYjq5v2LIssZJtaYGm_QQwbd5ssHoSFrcjY.cache +3 -0
  36. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/69/69rHH1VMRR3mpGyh9DAV0n6mmjTNtjkPLhjsMWTEHHc.cache +3 -0
  37. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/6m/6m-pr002PuDw2yTU5yFMHZr_Yrccz60ji4gNVHFEkAg.cache +0 -0
  38. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/7G/7Gly1atK83fTrN51FSQGTgnfn97DjgF8SBQR1Bd3U-o.cache +1 -0
  39. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/7e/7eF40Rm_qyH_4Nm_68U1-tDsetTS9nMq8YE9yIyXckw.cache +1 -0
  40. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/7e/7ebo33Vd-l__3L9Fxb70DEROgy8a74Ej0vpx68vELLs.cache +3 -0
  41. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/86/86TK63TT3eKKPtgVOilhedFmln3GU_gNl8SLwnYUpVQ.cache +0 -0
  42. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/8N/8NBHtc1wobpJfiL3tQjpLu8BMvUA4zKT4txyVqj2y50.cache +1 -0
  43. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/8U/8UoDUqI-BUttTAhww61lOM_rkXVyvKOGT3T3VKoG5tY.cache +1 -0
  44. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/8X/8XKLpGd9EuzDeOGXNoQhjx_O_l7g5PNGEfgQQ3B7RmU.cache +3 -0
  45. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/8t/8twZMW-FUpP8p_OEa9QreZAxiMMdK9HkBXmNeXP52S8.cache +0 -0
  46. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/9K/9KbuswPTMS7PawTuPAvnzj0MWDhLamr9MZs9NB8LbF4.cache +0 -0
  47. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/9N/9N9UzZTf_8cp-J0Y5mJNBEv-q6deiDxWz3qFhAVyEDY.cache +1 -0
  48. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/9t/9t-rXGMpFphptuPIUcuZ9cuhRjg5hgzMR5l8B_Ldr68.cache +1 -0
  49. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Aa/AaFwiOQMywTIyc3a1hlGpA2c5iHODYmUtUo6zjWEV7c.cache +3 -0
  50. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Aa/aAkEUPRPYtYYF3E-1WG70JrvxCvm8MgfxNnxUqUhSp8.cache +0 -0
  51. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Am/AmVg_Jj2o4JM_UGqemT3K8XI_PDuZPFEph-nXP4KoH4.cache +0 -0
  52. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/As/AsL4XHrP4VKkEKkO_MnQnc_SJHe22utc2-lTOHTzCig.cache +1 -0
  53. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/B2/B2HuSfJz1cPCkvjRca5XDAvsZf-1Njnsg6eqwit2yyQ.cache +1 -0
  54. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/BE/BEBiuAKKv_b5JU2nAsuDuxKSzxeNVm65zCUpMTaXuIQ.cache +1 -0
  55. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/BE/be_8pDtyM3BfBjCqSUO1VXxHrUBEfr0TOBKXSOCU0RM.cache +7 -0
  56. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/C7/C7xwxKSOmqUwd7QVyJnosVPYIJyWuWOznENeca7n4v4.cache +1 -0
  57. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Ck/Ck14ZIbAAZVzvFCo_i-wOcxvZ-sPWGAPjJrSN0ktCZ0.cache +0 -0
  58. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/DT/DTzkFbkAtx008DAK3DZuvHWHmEe8YVl_DnYs0DyL8GI.cache +0 -0
  59. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/D_/D_Z1zIyT7v84IIMEZo6Js1wyN3zJOtu0XdDVBn-K3H4.cache +2 -0
  60. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/E7/E7iV-VCGhKOb9ALHXIp0x_n4iInQ_Nb-kC94j5RtvTI.cache +0 -0
  61. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/E8/E8PPnVqWdHywt7FoP_EQijQkkTuDxAaW1TVURKYMyG8.cache +1 -0
  62. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/EZ/EZdj1Bl4liC1AHdINp1S9EW1eQBzMuRt32WLRRNYtXo.cache +0 -0
  63. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Ed/EDsKjKgBzcSckInqeRWc8HrA3ge785W1ays_6sgf7Hc.cache +1 -0
  64. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Ed/EdgdBZrG0e9RH-iHerASLLjfp13_RvY9Lvx4RIVBNq4.cache +1 -0
  65. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Ev/Ev3oOkLEmQubGb-eCdBSmjscsqJhLYoX-o_i-ZFSOzU.cache +1 -0
  66. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/FE/FEdryRZiKVEuoH0iH3nGUYxkM7Sa23yajyYWzrsbHjY.cache +1 -0
  67. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/FX/FXxWz10FR_us4RdWWUBML-E7OENaRWEPpwMcLhfO_Fo.cache +0 -0
  68. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/FY/FYqN2Ac1j7BMyNogLx_cteuh7_1dBaxhWd-_c_Wo2E0.cache +0 -0
  69. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Fc/FcYQnFc4I3un07fEZ5l0F1_SxepCRCRKKKj-jKCYFZ0.cache +3 -0
  70. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Fo/FoSMs5aq7Xv-kvf1WuRifL92pz-Fgfi8LRPfiu5FHYU.cache +1 -0
  71. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/G6/G6MikivBUN2KUBjrHGGIC3wENlINFcIVCw6Gn-ddCdw.cache +1 -0
  72. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/G6/G6yucKm37FVAIuk9tbwva8kBbP43R8BbWIqUH07erVc.cache +1 -0
  73. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/G9/G9HZWSg_gU5oyY0JQ6Ey0mPQD7z9dyvm5Se7bMZv44U.cache +0 -0
  74. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Gb/GbXpghlwxL3-D34h-js5lxV-Zcg5mVVIuSbABCNUG4k.cache +54 -0
  75. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Gk/Gk3FEPItxd0G8f_9qMSIUELpMBd316BhlZv0BKjMg9w.cache +3 -0
  76. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Gp/GpuHwTT4pDxN3wYMqvJUaQieM4usp4K6aLosDOSHeh4.cache +0 -0
  77. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Gs/GsCFFBB7vqOuUIwK2R7ojH-h0easzXhEik8PPwK0rbA.cache +0 -0
  78. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/H8/H89KGYfXFNK9mUxAJqaq9z4-ZKjQebFZvNuMiKv639Q.cache +1 -0
  79. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/HS/HShYUosSZKIUMEo8BEq2R4hFcf8H1_BDJUSs4dlFP6k.cache +3 -0
  80. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/HT/HT2kN19u1OcyfoZO7XYbF4WJzw0fiCgKu0dn47x2jPo.cache +1 -0
  81. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/HT/HThMz-Cjbn-rFt8whApH3ZTUgYA4FYAwMzeAYd_RlvM.cache +1 -0
  82. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/I8/I8DnWLuQhuhWpbPrnCz1fphFbItKDnf55C_wHzY8LYo.cache +3 -0
  83. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/IW/IWIrxSp8b0ijG9WhjHUcI4ItxST45hha3_y-qcCIqMY.cache +3 -0
  84. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/In/INZ3M6aJG1VyG0dAE9RRhZg8HJFTrna7H4hAW6Htkxg.cache +1 -0
  85. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/In/IntFFrdNm3Z9thZKc1TukosqhX3kTubxyKDi4LgGJdg.cache +1 -0
  86. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Iv/Iv1eMKXC6HYUPOM6s5lWfGSpquaXSOjB46LeddlLEa0.cache +2 -0
  87. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Iz/Izk1nqGo8c-jzgUhOIesyTu1mSJMEFNvhy0X98X4N_I.cache +0 -0
  88. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/JN/JNdbDdWZkpmHrs-l_DtWYVoBZgYFfk-NO9JDhFL07MY.cache +3 -0
  89. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/K2/K28WZ7CVE4r2FcrzlB3LwdMKA3LrPIaaCfDvO3pUMCE.cache +3 -0
  90. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Kb/KbtPuR6P0LmOAkE2MX-taOFtwj0Guc_JWZAjwowJsuQ.cache +1 -0
  91. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Kd/KdKTsxUH-rphnRhirijVLW9KRM2uGKUOvjIulnLI2tY.cache +2 -0
  92. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Kn/Kn3GTp-awnb2ge3KQkMJP8bOTW7m0V37vAhd0x-6P20.cache +73 -0
  93. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/L-/L-P7DErCeB11t9VDUaotF9wkPDAOeyvrG0d5sII281w.cache +1 -0
  94. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/LO/LOIw_QrLu6EqRv2po1AhlmvJ5T0AcIZuJV0rK15RRx0.cache +2 -0
  95. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Lb/Lb-EGRk7E0qDE9p8Hqjkx6MpCebFJOvPxPkfqu-ITng.cache +1 -0
  96. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/MK/MKSn3iii8fftCls3xw4XwTGICzZh2OfVqxKiwo6psTQ.cache +1 -0
  97. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/MK/mKYeqBhwhMfHnyIshyjiIYfk3cgRWGS-BqkqE48T_xg.cache +0 -0
  98. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/MT/MTc4quu6XDggHl_641Gv2UFv55Kttrhx49TkYDhmEH8.cache +0 -0
  99. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Mc/Mcd2DhI9dXIrZ2qk3vyeqp8MlR3-uhumgu7L1lZq84o.cache +1 -0
  100. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Nr/Nr_lRFccJIQhRupPc0IYXf7_0K85m3XNcOQ26s01wdg.cache +1 -0
  101. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Nr/nrLpo0Li-lZKBQgFvoYBYk6oVgbgDKpiy1zgT0cthlc.cache +1 -0
  102. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/O8/O8akbUwAbmIKY-AhITimq-JDQ6IgsO3Hvq2v5etufFw.cache +2 -0
  103. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/OZ/OZRjc9y3CedBSOBSwEsGIEcaz8rJcSHucMyKrlKRzvA.cache +1 -0
  104. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/O_/O_LQ9rTo-ySqWYbC7zLFnus7phfUOitpjyLozLTHb6k.cache +1 -0
  105. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Oi/Oi1nr81Bfmxe3X2tEmifRFoGnXev1CbJYKTYal8365A.cache +0 -0
  106. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Ow/OwccXl1Ic3lqgRBGIYGM5tadia8IdkfUeJMmP4n1tTM.cache +1 -0
  107. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Oy/OYMZbkT20G0_iILqjfr63sCmV_trlMdxLp1WoltE8AQ.cache +1 -0
  108. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Oy/OyVt39k9qOctveYmFl-STXKJKNeueCyOEbGZ2_B4ZD0.cache +3 -0
  109. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Oy/oyFBxJ8Z8i2Xb2Lll4uH6W2A3f9vSVhA9oXM2r-0R7w.cache +5 -0
  110. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/P3/P3WVCvTrDc2yHhngtC9uXOAewMmWcXdPi7ASSDrV5lo.cache +1 -0
  111. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/PC/PCjtAJWBdT0swUVHaAWwI3bojT1phBdmw9HQisn_pbM.cache +1 -0
  112. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Q8/Q8A_ahhm51CmbHk4WpTRCpwtI9mxcu2bW6NqhYdcfwM.cache +1 -0
  113. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/QX/QX0JH72se01xT2fNmLyg-sUtrk7DlLmkxNV01s_MEfg.cache +1 -0
  114. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Qv/QvrJG0y21_i6f_tzu-nClfX01QyRZF4QIkZ-4um5r_U.cache +104 -0
  115. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/R9/R9NVbLRnVzczRdRyD2VV5x97VrIowtBQLyypSZBQt90.cache +1 -0
  116. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/RE/RE53knr2hrEvDFyr33gwJBL7twGjHEmN6s6FwGtyKFs.cache +1 -0
  117. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/RM/RMsrl8AKW4-xiwQlQyHKpF51XeuKQGv6VcSj6lpC-gg.cache +1 -0
  118. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/RQ/RQUnHc8WheunBLgn7V-Yrrm9cdYxr1fqAp9jNkexDrg.cache +2 -0
  119. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/RU/RUWGCr1p2-QM0JD8NwJpLrWrH3UwTw8ypOEEnyaHRgM.cache +3 -0
  120. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/S-/S-vKRdJnmmIzYIa4KShhx689AY-lTdGFd44UYa-DLFc.cache +1 -0
  121. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/S0/S0weHOttlNPgxahIyNUKB3qj2vN71d526XRHMxMje9Q.cache +0 -0
  122. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/S7/S7lL2J7tx5oHCtsOvZuBoNGOeOoe4n7qJgZCQGHXfYQ.cache +3 -0
  123. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/SM/SMlFyPb3qixKxxPQ6XSkdrOSDxOFptdM4jt1AK4Mync.cache +0 -0
  124. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/SP/SP1YDfGWTQNPPbv4TlimqUvdr1n3QAj3ceHunawMq88.cache +1 -0
  125. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Se/Se8yKp4PKGEiDiwrH_AL_pSzl6CRnCa2VyaOv5zUj1o.cache +0 -0
  126. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Tf/TfIQqzFTX0vKu3IJM4C9An0gkeY0WFFZebfDYcQKQ60.cache +2 -0
  127. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Tj/TjiJSeh-VRpcoiI0Z_JvKlg2jE3lGsKkLwCvGsxTVhg.cache +3 -0
  128. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Tw/Tw4qTe4pikph13nkN4d8AZjSb8F9Z8zVlmNjfMNiDMo.cache +3 -0
  129. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/U2/U2Gr71iJOUl-Ydg0rMZBlsTM07x5MlSWPokr1lBwF-E.cache +1 -0
  130. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/UA/UASYkjJr9XL3Lmr0L5lWqDRLPJ7Ap9rk_VKVTkM3Q3Q.cache +1 -0
  131. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/UG/UGa0U-476ZNYV3aEVKwnEUoTXohti_85esgeDAtC_BA.cache +3 -0
  132. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/UO/UOPeDrSCvYLR_Fyw4iPO7bsBQqo8-BpzBB5GlJBopZM.cache +1 -0
  133. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/UY/UYcoe2gw7Ke7pEASDPCU4GSnL8fzo8QS5k5xOVJCk3U.cache +1 -0
  134. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Ud/UdxiCBYFzfE8nB_w-gcXpjYo9RQN5bhe6iwmsvNoMhE.cache +3 -0
  135. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/V-/V-7ZMoSNgEgBzS6M_LwBK_4N7MxPjyvUYchxsVCmBDM.cache +1 -0
  136. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/V3/V3VGAxQ3BvryMb_SnWDEYPMHj9zs5FzSD641sbWPjSo.cache +1 -0
  137. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/VB/VBrI6MZEfEAzYQj1PQbGjhxHf4TaI3VrxO2bqpfTjj0.cache +3 -0
  138. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/VK/VKGnil96gVh9Kck5z8wxfQ-9msIJjkjLnQZ2b8XMhfY.cache +3 -0
  139. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/V_/V_2BcaJttZWkKJHdfrM2v04okvdAGSxW0SQ3rkwxJvM.cache +1 -0
  140. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Vs/Vspr6E12ZPcDDrfEFKL6ba5UK_SbpQi07kyw2ILTBNk.cache +1 -0
  141. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/W_/W_dL_pApK43bcE2g5lXwOf3ZHkFUmaNTnWceZz1CHo0.cache +0 -0
  142. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/W_/w_sXspjWODK2ApqfRBF_sKQi5hFIVuZuWqISpnxTefE.cache +0 -0
  143. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Wi/WiPaSahUX5qyQtuSi4aWFHUY4RRbTpleVQBJWsqvDFg.cache +1 -0
  144. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Wu/WuHL0qKgH6ZWO0xi1N0_F-L9chmMwlEws29DipzK7i4.cache +0 -0
  145. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/XP/XPG0OQg_5xBL7_XGSAB6ruND4NZRsicqwGihb7QfgKA.cache +0 -0
  146. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/X_/X_bRAdkpQIWNFyBCdNXCJqteo2utcpaQpv9V4YQE3OQ.cache +1 -0
  147. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Xi/XimxZHdFWVLh8hQab9TCpu4t7DTp8MBGP1_SEZ6Cnxs.cache +2 -0
  148. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Y4/Y4PclklRbbVX6Acy3DA_YzrhNt3WEQkRqZ677XpiLRc.cache +1 -0
  149. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/YG/YGdG9wrRMRcR_iITaLv__Abu-IoHqhdPZfP5k4s6T2A.cache +0 -0
  150. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/YO/YOADM86O0eaqQpwNTmvhU1ArE_pJ2l3pQ-tsCDYZLec.cache +1 -0
  151. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/YO/YOrKIrDaBMyp989-0d7RjAOGcCESA8wZhtagnByGmVc.cache +3 -0
  152. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/YR/YRS1gAx6MWMkF04LBtqmFEb47i6X3i1nwRTHi8u-Je4.cache +1 -0
  153. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Yd/Yd3_dnSRf8H7Df3u1spB2vUso6M0WDutGEqXUOwZDWI.cache +1 -0
  154. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Yd/ydw1ho6l1Elu8E4sv2Pn65RmkgGhDQ0OlujSJlGFgPo.cache +0 -0
  155. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Ye/Ye9C84pAvhKWoqAduD9R7jiiUfpO1_5MfwPHPQyMSQs.cache +3 -0
  156. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Ys/YsRjDc40EirSbmV2_PUdU5IsK6XvVgyfnpwJNPz1Pwk.cache +3 -0
  157. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Zk/ZkIfGkcCJSiftkYYunIxnzDnAamuZaL9x5ulbwiKrIE.cache +3 -0
  158. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/Zo/ZofRNaIwOcCjvdrVkwSlvhd9jRO3QapQl9xH08DGz-w.cache +1 -0
  159. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/_3/_34TKSBAHO8RGnZnJy37nrGK8p3P4EG2rI65OW2ZH78.cache +0 -0
  160. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/_d/_dA_64XleYGAVMcz6Ge-7Yb9__m9Hf3ZQ_jZHN6-f_0.cache +1 -0
  161. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/_g/_glx-WMt43JuezTWAI-GM6HieDwxOsrSzqYwcLerQDY.cache +3 -0
  162. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/_t/_t1tLqXmi1lHiSlwmU-zSZVbcBPJ3j9rRBbHSutcgpo.cache +1 -0
  163. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/aE/aEAkRAdMBJp7IrmAyKIzkh6UUsm6OaeRzQ-T5CHP2PA.cache +0 -0
  164. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/bd/bdRhpZ6VD7GNUv40StMsfowJEjlZCvAVLNW6q99Zzhw.cache +3 -0
  165. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/bw/bwQdQakeOA80sOssAi0AL0eCbN7jTYZdMWZY-7ghdmA.cache +0 -0
  166. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/c8/c8D39zSpjZ9lxfWJLahsQcz7AvIzZmZ7bSYEo85dxzo.cache +0 -0
  167. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/cO/cOBeuOQojpWO_MSC_nk_O-OfC-tCXz1V4d4xXcu_QwQ.cache +0 -0
  168. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/cg/cgXlwVggiz17racws5jMBrsSPqIWMY9mDl9enuvFCUM.cache +1 -0
  169. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/ch/chbXFl4E9bqZVTpC3IxzIUCkGDMX8pvm8Pxjs2LYSrM.cache +0 -0
  170. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/d0/d0rr17-3lWfRQ0Wo55j8e6YNQ9itz_RBh-3RqCYlcM0.cache +0 -0
  171. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/d3/d3wnBf2fkXxkR8-XxMzkRCr1oyarxSOC0L9fH6LKbv8.cache +0 -0
  172. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/d5/d5ppfzn29-UhjtDhCsMsdotk_GVxTYT0xg-DEHIcYwo.cache +3 -0
  173. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/e-/e-kcN4_NtWHjaNUnMJoSiqwEz4dirmu2QiGwblFRk-I.cache +0 -0
  174. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/ec/ecdv8EaiQV_ma8QCsB7U88kjF-tTfZQb7bLiWnro5us.cache +1 -0
  175. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/fD/fDQxtoKk9UP8CxHIDc1841LNAFdH7Sda9GwhYqiKWxo.cache +0 -0
  176. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/fS/fSD-q4iDT__seP_fNO7tq5w6RX1QUA7Kyj4lH8zmHhU.cache +0 -0
  177. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/fz/fzgRkEKX9VfGmqVCl2cdeuc8BzxtZsh4Wi2HEbCqyZI.cache +1 -0
  178. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/g2/g2Wl8vGAQHSJ00zXGw74Ywrw161dkkv75rySfk6TF1s.cache +0 -0
  179. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/g7/g7ctztTZ8C8Og4cjS0esPTqZRMrYHawSQoylHFuq5Tk.cache +2 -0
  180. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/gH/gHZ91xw-QZ6XiSYGHx-zvUaMvj1jRHv32OXYWGesyzY.cache +1 -0
  181. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/g_/g_AyDddrdALmJv_racfhwX-MXCzhMhSiJqBBhkOXJSI.cache +0 -0
  182. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/h0/h0C5r1YmxeWZ7xmvBZWPFnske5XtWCy8IHKEhYxz1GY.cache +1 -0
  183. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/h4/h48kbOdKbM4E10Vs0wVgEhr4-FhMTf18RB1lLBm1LUQ.cache +1 -0
  184. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/hu/hu3COgettdZo3gMm8DPcQBAUu3l0zxDiLm84wQt5Kwg.cache +0 -0
  185. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/i4/i4pF9Bmmu2_lS3v48TNP2C1MUPf7EiXjedNwl7_X8D4.cache +1 -0
  186. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/ib/ibRU-oP7ekrNYNIM0ERyOPouLBngmxnDaHp14QYNCQM.cache +0 -0
  187. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/jD/jDPIMat4OMQzKLeqRF3Nb4kY9HLS4usXrYZWerxFUho.cache +3 -0
  188. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/jF/jFxYi7n0kw3Ev0DMfVbN0BYm7i9ZAWb-5lrTgQLkzkw.cache +4 -0
  189. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/jr/jrOrf3u-MWeBtMvmEPyVhHjRRDWY60ycXP3G9S6PxH8.cache +0 -0
  190. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/kK/kKUwBWRfsfIkHyKBuznJcpd5W2quP1WG0Qvm8SIong0.cache +2 -0
  191. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/kL/kLvC5Jztau9WmLo1_LQBFT9R6XnmXYSuQHTmhVwLBnU.cache +0 -0
  192. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/l7/l73JBt8d21O2R5jHuAoSF1t3yac5sUyTRinAHEA7Nro.cache +0 -0
  193. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/lL/lLc5z7qdJY4WfFBzyGhJnOF31wBBqJoD4OAxYPy23oI.cache +2 -0
  194. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/lZ/lZxqodqscAFPbLUWfizriuYB0LstFAJEmIZIknQGjf4.cache +0 -0
  195. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/m4/m4qnz1XKKl5TmVc_nfNUxnDOcWIF3vjCrybysx5S5dE.cache +3 -0
  196. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/ml/mlDzBJPZseI3ONA4G-cFVXRf67T5l11vzlCZuXNLCqg.cache +0 -0
  197. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/mq/mqM2btO-0T9M5u_Apb-hnetpL9Ot0Za1lmhmbkazXJo.cache +1 -0
  198. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/nK/nKQZUwnWgjgSHJRzgMX6T1rS0o5OXmCUNf7kOwDWt-Q.cache +3 -0
  199. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/nq/nq-FMjeOP3ccPBV3KIWlsIXz00Y-DxcZLDbMy41w0ns.cache +5 -0
  200. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/nv/nvMFDG0qM90wst7hl2gCp72SUCmYoFYvoZfxyk7F3-w.cache +3 -0
  201. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/oA/oA0wFKJ3fV76DLsMuI5FYOv7KArBhjcmuMEBUVh-IEI.cache +1 -0
  202. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/oG/oGWbT11h9CntgsRYeHVvRUSRM_pXctuvso5bD1E-_Rg.cache +75 -0
  203. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/oJ/oJf6gvISJUzPzOZfzlm0RPXE8pkRsk4Liou1wiR4bwU.cache +1 -0
  204. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/oS/oSsCcH0Y1Pb72IewPEMMZgthmjZ-aBCsmPRDQY6IsWE.cache +2 -0
  205. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/oc/ocCdznCTiDsf5SnX-XbzboHKIsa5N_0JJvcFaIa0v4k.cache +0 -0
  206. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/pZ/pZs_OT7KhpWl5Bw2QXAZBUJv4L4B0ZvjroNOOVNYHew.cache +1 -0
  207. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/pi/piPpAsxRDhkhXCpgy5rNfwev2FCllQeOpv2T46jFlgk.cache +1 -0
  208. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/q4/q4iH6hAaHRsNLtNNQwjyuV1nrRqUqSvOP2tOLHUWmw0.cache +1 -0
  209. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/qB/qBoVS2DfU2y1_uaxk__lSg4q7qgpRjZ0yCRA62ViaSk.cache +0 -0
  210. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/qG/qG4Hk7ZYCV4GcPgAVWFnzBPzGUXMjsPNlWAxzXFDIzY.cache +1 -0
  211. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/qh/qhdWM55QpY_1Wel6alhcgtJJ1o1i_pvD5m4pR7Gf2H8.cache +1 -0
  212. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/qi/qiZJ4AD7a-JZBnkgliJipAqlqobsszSWew-8qJMEBuc.cache +0 -0
  213. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/qn/qnxANHDXRgytq0YwdMMqTCjJkR_7u-AIYodo6H2yWZk.cache +0 -0
  214. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/r2/r2wUxqXPZGyL8yJQ8xQKBW62cJs1uE_kUeiDnjOt3eI.cache +1 -0
  215. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/rI/rI8pww981NHG22krf5FbLsuRHjYf85Nlom5uxJQwoqY.cache +1 -0
  216. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/ra/rahIaRydDKWOwY0mWr9MsvBG5ia5q8RgLBZsVUS1Z-k.cache +1 -0
  217. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/rd/RdfB0OzMfmjFAubT3THbRNJY7_LwFJZJKrUGU8q3708.cache +0 -0
  218. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/rd/rdiz0vLTLXOjXgmyGaa9Rtn9U1rxIR70X39htU2l0uM.cache +2 -0
  219. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/rg/rgsvMxrjiJSAFeE_Rawd4cjIlNniYQ2LLMr-WfHcEmE.cache +2 -0
  220. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/ro/ron72ZitBqwTzm-mJk-_TnXub4HXPM6x0Cv4FSERVJA.cache +0 -0
  221. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/rw/rwAUBS6_7P7KsaV-huzkfaoGbbPCL_TLREXtEGxNGto.cache +0 -0
  222. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/sR/sR2TAOkCQmj-R7OEG_CPlIBvcf5qxFqq5uwJ3n7GHyQ.cache +1 -0
  223. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/sX/sX4wwS_efcIabnhLoa6LYb_lRY5Zv2E_coiw4-cgESg.cache +1 -0
  224. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/sb/sbIfIYytasmqOfY26ylrPhJnvWLmgYauZ6XOjXMjssU.cache +3 -0
  225. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/sj/sjeKBH2T__mODBuQr0RqtBnDJeyDutqYZ1fssGam_rs.cache +1 -0
  226. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/tN/tNZQPVNwKhR_JK2mlhPvLHQxlrN8Fk5prdVXg5x7CLs.cache +1 -0
  227. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/tP/tPF6H9NRpGO3whu2y5_e_R_1EACKdCwu5437D83qJT0.cache +2 -0
  228. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/tY/tYhhOTVTALHMYiY0UZ1-mTCJDNXZ_a8SB9nDvb4fZKs.cache +1 -0
  229. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/tu/tu6UFqTPo1b-UrtPhSJXYAfv2t3ba3adAGKGi-RaEuI.cache +1 -0
  230. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/tx/tXTuLOynyl3e0YWQyhD3E50mipG6rWV5rJh7DUIJZmY.cache +1 -0
  231. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/tx/tXbf5ehiC_jNJ1nYVORlPm8XC5mukmFnPBDopf4ds3U.cache +1 -0
  232. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/tx/tx4eRwuD66QCa9fWI5DpiQsC6TjXTndahVzhzsqxezU.cache +1 -0
  233. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/u0/u0t4_vnTeokERX9UCHD5W7IMs8CV2wE5Y2Zh8ozQtd4.cache +1 -0
  234. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/u3/u3Jt2hHm68soUkdfP4pUF2RbuciMhpJMZaye7golzjk.cache +0 -0
  235. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/u4/u4UmICDQX9_TmlF9dagNGljgWQwWxyJcjHARwcmhgXs.cache +1 -0
  236. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/ur/uRZ3Og-L4J6uWe9e35T_tOklxCVrd94Ke4q8fVELXX4.cache +1 -0
  237. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/ur/urq6cvvM8i1tBGilXO29tzaeGpWTgFWe8wgrQyBGQco.cache +1 -0
  238. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/uv/uv3cZO4PygxIjlJsSwYJwyHrVVqObs2ACSK1ZDpciXg.cache +0 -0
  239. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/v6/v64K6Lupt6J92uk_MwUXTfGMobanMksIxKX-zamg8IU.cache +3 -0
  240. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/vN/vNGzkJNd8jZKUpldX9gm2gb3QR8CJRHo72vHHMHPVYU.cache +1 -0
  241. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/vf/vf6pS83AJcKYSl-DcY_ScZeYkB0yDhbxKl_jnVPColY.cache +0 -0
  242. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/vo/voUX3N1PGX-aokkt4gRSJMc0ZaWrL0i2pGo-9--xDvA.cache +1 -0
  243. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/vv/vvmwM1iU3kXTcgVdOcdKSaTOp5RCXRv_xvb7AZkL594.cache +0 -0
  244. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/w5/w5QMt63TSr_XbGyWPix58UVdQew5zaVFIls9Q05leCU.cache +2 -0
  245. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/w9/w9EGr404Ec8iWX-TW5NwtOX7CZFxbLuJrLrPXegwie4.cache +0 -0
  246. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/wK/wKaiZcrtqWwNr8hquK3JBngxCtsqbKMMPfUlBZB4FAo.cache +0 -0
  247. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/wQ/wQdUXI6R5rwkq8dRFsjrgiJ0E6eF_0M75B_SxoMK8-w.cache +1 -0
  248. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/wV/Wv-6bVwsTp_LqZ1ZD4iZR8kOhuIO4M5yCctID5n98Q8.cache +1 -0
  249. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/wV/wVjAOidZ-lZqani0lwAeuul_ma2e9nNZfuEQgaqZ6N8.cache +78 -0
  250. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/wg/wgvpP2Zxu3BaOgAP1nz0MTp3TnSPZLLD7njzJyTAY0k.cache +5 -0
  251. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/x-/X-GTjAJs0k4DdFqoUzfRXbSpu0lHkC7WuXFo6i9mtcQ.cache +1 -0
  252. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/x-/x-n_OHI0W_PinN8NC6kdtfkflbqTvZTEzWLZBGotSvQ.cache +1 -0
  253. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/xs/xsz1Xli1rjewlmkdAsFaTqU1QF1bAZ9r2VABTS63a-E.cache +0 -0
  254. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/yH/yHR_S3o-CR62iV2PhE_BBYQANZqqn1Hun_xVebhOx0k.cache +0 -0
  255. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/yM/yMGwsY99j5fPgf5LWsCwNt4JJdvIJ8T1A9tnEgiNG3k.cache +1 -0
  256. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/z4/z4R50-aot5DTt3qdrnIv3L7tzYF5Ts_OZ_UBkdgZQew.cache +2 -0
  257. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/z9/z9RyRiOc7eWfq0AQht0-e2T8BCDWGxuElTNRNyF-i60.cache +0 -0
  258. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/zQ/Zqlhmo8u-4j5v6Js-q3mxfbqc-DM0nZ3rQUiMMdtQnQ.cache +0 -0
  259. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/zQ/zQpUaxTk07z9j0wKNLDhvRU1cCHLOPsB8nftF3rwGTg.cache +0 -0
  260. data/spec/dummy/tmp/cache/assets/sprockets/v3.0/zy/zyyLbt3lCJcXlGtjIxh7PoGOlX3t6Sr00yVzT6jhtx4.cache +81 -0
  261. data/spec/dummy/tmp/pids/server.pid +1 -1
  262. data/vendor/assets/javascripts/medium-editor.js +443 -114
  263. data/vendor/assets/stylesheets/medium-editor/medium-editor.css +15 -5
  264. data/vendor/assets/stylesheets/medium-editor/medium-editor.min.css +1 -1
  265. data/vendor/assets/stylesheets/medium-editor/themes/flat.css +1 -1
  266. data/vendor/assets/stylesheets/medium-editor/themes/flat.min.css +1 -1
  267. metadata +523 -11
@@ -1 +1 @@
1
- 8
1
+ 259
@@ -385,7 +385,8 @@ if (!("classList" in document.createElement("_"))) {
385
385
 
386
386
  (function (root, factory) {
387
387
  'use strict';
388
- if (typeof module === 'object') {
388
+ var isElectron = typeof module === 'object' && typeof process !== 'undefined' && process && process.versions && process.versions.electron;
389
+ if (!isElectron && typeof module === 'object') {
389
390
  module.exports = factory;
390
391
  } else if (typeof define === 'function' && define.amd) {
391
392
  define(function () {
@@ -628,11 +629,10 @@ MediumEditor.extensions = {};
628
629
  splitEndNodeIfNeeded: function (currentNode, newNode, matchEndIndex, currentTextIndex) {
629
630
  var textIndexOfEndOfFarthestNode,
630
631
  endSplitPoint;
631
- textIndexOfEndOfFarthestNode = currentTextIndex + (newNode || currentNode).nodeValue.length +
632
- (newNode ? currentNode.nodeValue.length : 0) -
633
- 1;
634
- endSplitPoint = (newNode || currentNode).nodeValue.length -
635
- (textIndexOfEndOfFarthestNode + 1 - matchEndIndex);
632
+ textIndexOfEndOfFarthestNode = currentTextIndex + currentNode.nodeValue.length +
633
+ (newNode ? newNode.nodeValue.length : 0) - 1;
634
+ endSplitPoint = matchEndIndex - currentTextIndex -
635
+ (newNode ? currentNode.nodeValue.length : 0);
636
636
  if (textIndexOfEndOfFarthestNode >= matchEndIndex &&
637
637
  currentTextIndex !== textIndexOfEndOfFarthestNode &&
638
638
  endSplitPoint !== 0) {
@@ -1019,6 +1019,11 @@ MediumEditor.extensions = {};
1019
1019
  }
1020
1020
  },
1021
1021
 
1022
+ /*
1023
+ * this function adds one or several classes on an a element.
1024
+ * if el parameter is not an a, it will look for a children of el.
1025
+ * if no a children are found, it will look for the a parent.
1026
+ */
1022
1027
  addClassToAnchors: function (el, buttonClass) {
1023
1028
  var classes = buttonClass.split(' '),
1024
1029
  i,
@@ -1028,7 +1033,13 @@ MediumEditor.extensions = {};
1028
1033
  el.classList.add(classes[j]);
1029
1034
  }
1030
1035
  } else {
1031
- el = el.getElementsByTagName('a');
1036
+ var aChildren = el.getElementsByTagName('a');
1037
+ if (aChildren.length === 0) {
1038
+ var parentAnchor = Util.getClosestTag(el, 'a');
1039
+ el = parentAnchor ? [parentAnchor] : [];
1040
+ } else {
1041
+ el = aChildren;
1042
+ }
1032
1043
  for (i = 0; i < el.length; i += 1) {
1033
1044
  for (j = 0; j < classes.length; j += 1) {
1034
1045
  el[i].classList.add(classes[j]);
@@ -1429,11 +1440,15 @@ MediumEditor.extensions = {};
1429
1440
  },
1430
1441
 
1431
1442
  cleanupTags: function (el, tags) {
1432
- tags.forEach(function (tag) {
1433
- if (el.nodeName.toLowerCase() === tag) {
1434
- el.parentNode.removeChild(el);
1435
- }
1436
- });
1443
+ if (tags.indexOf(el.nodeName.toLowerCase()) !== -1) {
1444
+ el.parentNode.removeChild(el);
1445
+ }
1446
+ },
1447
+
1448
+ unwrapTags: function (el, tags) {
1449
+ if (tags.indexOf(el.nodeName.toLowerCase()) !== -1) {
1450
+ MediumEditor.util.unwrap(el, document);
1451
+ }
1437
1452
  },
1438
1453
 
1439
1454
  // get the closest parent
@@ -1653,6 +1668,19 @@ MediumEditor.extensions = {};
1653
1668
  */
1654
1669
  setInactive: undefined,
1655
1670
 
1671
+ /* getInteractionElements: [function ()]
1672
+ *
1673
+ * If the extension renders any elements that the user can interact with,
1674
+ * this method should be implemented and return the root element or an array
1675
+ * containing all of the root elements. MediumEditor will call this function
1676
+ * during interaction to see if the user clicked on something outside of the editor.
1677
+ * The elements are used to check if the target element of a click or
1678
+ * other user event is a descendant of any extension elements.
1679
+ * This way, the editor can also count user interaction within editor elements as
1680
+ * interactions with the editor, and thus not trigger 'blur'
1681
+ */
1682
+ getInteractionElements: undefined,
1683
+
1656
1684
  /************************ Helpers ************************
1657
1685
  * The following are helpers that are either set by MediumEditor
1658
1686
  * during initialization, or are helper methods which either
@@ -2416,6 +2444,26 @@ MediumEditor.extensions = {};
2416
2444
  (function () {
2417
2445
  'use strict';
2418
2446
 
2447
+ function isElementDescendantOfExtension(extensions, element) {
2448
+ return extensions.some(function (extension) {
2449
+ if (typeof extension.getInteractionElements !== 'function') {
2450
+ return false;
2451
+ }
2452
+
2453
+ var extensionElements = extension.getInteractionElements();
2454
+ if (!extensionElements) {
2455
+ return false;
2456
+ }
2457
+
2458
+ if (!Array.isArray(extensionElements)) {
2459
+ extensionElements = [extensionElements];
2460
+ }
2461
+ return extensionElements.some(function (el) {
2462
+ return MediumEditor.util.isDescendant(el, element, true);
2463
+ });
2464
+ });
2465
+ }
2466
+
2419
2467
  var Events = function (instance) {
2420
2468
  this.base = instance;
2421
2469
  this.options = this.base.options;
@@ -2431,7 +2479,10 @@ MediumEditor.extensions = {};
2431
2479
  // Helpers for event handling
2432
2480
 
2433
2481
  attachDOMEvent: function (targets, event, listener, useCapture) {
2434
- targets = MediumEditor.util.isElement(targets) || [window, document].indexOf(targets) > -1 ? [targets] : targets;
2482
+ var win = this.base.options.contentWindow,
2483
+ doc = this.base.options.ownerDocument;
2484
+
2485
+ targets = MediumEditor.util.isElement(targets) || [win, doc].indexOf(targets) > -1 ? [targets] : targets;
2435
2486
 
2436
2487
  Array.prototype.forEach.call(targets, function (target) {
2437
2488
  target.addEventListener(event, listener, useCapture);
@@ -2440,16 +2491,21 @@ MediumEditor.extensions = {};
2440
2491
  },
2441
2492
 
2442
2493
  detachDOMEvent: function (targets, event, listener, useCapture) {
2443
- var index, e;
2444
- targets = MediumEditor.util.isElement(targets) || [window, document].indexOf(targets) > -1 ? [targets] : targets;
2445
-
2446
- Array.prototype.forEach.call(targets, function (target) {
2447
- index = this.indexOfListener(target, event, listener, useCapture);
2448
- if (index !== -1) {
2449
- e = this.events.splice(index, 1)[0];
2450
- e[0].removeEventListener(e[1], e[2], e[3]);
2451
- }
2452
- }.bind(this));
2494
+ var index, e,
2495
+ win = this.base.options.contentWindow,
2496
+ doc = this.base.options.ownerDocument;
2497
+
2498
+ if (targets !== null) {
2499
+ targets = MediumEditor.util.isElement(targets) || [win, doc].indexOf(targets) > -1 ? [targets] : targets;
2500
+
2501
+ Array.prototype.forEach.call(targets, function (target) {
2502
+ index = this.indexOfListener(target, event, listener, useCapture);
2503
+ if (index !== -1) {
2504
+ e = this.events.splice(index, 1)[0];
2505
+ e[0].removeEventListener(e[1], e[2], e[3]);
2506
+ }
2507
+ }.bind(this));
2508
+ }
2453
2509
  },
2454
2510
 
2455
2511
  indexOfListener: function (target, event, listener, useCapture) {
@@ -2609,23 +2665,23 @@ MediumEditor.extensions = {};
2609
2665
 
2610
2666
  // Helper method to call all listeners to execCommand
2611
2667
  var callListeners = function (args, result) {
2612
- if (doc.execCommand.listeners) {
2613
- doc.execCommand.listeners.forEach(function (listener) {
2614
- listener({
2615
- command: args[0],
2616
- value: args[2],
2617
- args: args,
2618
- result: result
2619
- });
2668
+ if (doc.execCommand.listeners) {
2669
+ doc.execCommand.listeners.forEach(function (listener) {
2670
+ listener({
2671
+ command: args[0],
2672
+ value: args[2],
2673
+ args: args,
2674
+ result: result
2620
2675
  });
2621
- }
2622
- },
2676
+ });
2677
+ }
2678
+ },
2623
2679
 
2624
- // Create a wrapper method for execCommand which will:
2625
- // 1) Call document.execCommand with the correct arguments
2626
- // 2) Loop through any listeners and notify them that execCommand was called
2627
- // passing extra info on the call
2628
- // 3) Return the result
2680
+ // Create a wrapper method for execCommand which will:
2681
+ // 1) Call document.execCommand with the correct arguments
2682
+ // 2) Loop through any listeners and notify them that execCommand was called
2683
+ // passing extra info on the call
2684
+ // 3) Return the result
2629
2685
  wrapper = function () {
2630
2686
  var result = doc.execCommand.orig.apply(this, arguments);
2631
2687
 
@@ -2755,6 +2811,8 @@ MediumEditor.extensions = {};
2755
2811
  // Detecting drop on the contenteditables
2756
2812
  this.attachToEachElement('drop', this.handleDrop);
2757
2813
  break;
2814
+ // TODO: We need to have a custom 'paste' event separate from 'editablePaste'
2815
+ // Need to think about the way to introduce this without breaking folks
2758
2816
  case 'editablePaste':
2759
2817
  // Detecting paste on the contenteditables
2760
2818
  this.attachToEachElement('paste', this.handlePaste);
@@ -2792,21 +2850,16 @@ MediumEditor.extensions = {};
2792
2850
  },
2793
2851
 
2794
2852
  updateFocus: function (target, eventObj) {
2795
- var toolbar = this.base.getExtensionByName('toolbar'),
2796
- toolbarEl = toolbar ? toolbar.getToolbarElement() : null,
2797
- anchorPreview = this.base.getExtensionByName('anchor-preview'),
2798
- previewEl = (anchorPreview && anchorPreview.getPreviewElement) ? anchorPreview.getPreviewElement() : null,
2799
- hadFocus = this.base.getFocusedElement(),
2853
+ var hadFocus = this.base.getFocusedElement(),
2800
2854
  toFocus;
2801
2855
 
2802
- // For clicks, we need to know if the mousedown that caused the click happened inside the existing focused element.
2803
- // If so, we don't want to focus another element
2856
+ // For clicks, we need to know if the mousedown that caused the click happened inside the existing focused element
2857
+ // or one of the extension elements. If so, we don't want to focus another element
2804
2858
  if (hadFocus &&
2805
- eventObj.type === 'click' &&
2806
- this.lastMousedownTarget &&
2807
- (MediumEditor.util.isDescendant(hadFocus, this.lastMousedownTarget, true) ||
2808
- MediumEditor.util.isDescendant(toolbarEl, this.lastMousedownTarget, true) ||
2809
- MediumEditor.util.isDescendant(previewEl, this.lastMousedownTarget, true))) {
2859
+ eventObj.type === 'click' &&
2860
+ this.lastMousedownTarget &&
2861
+ (MediumEditor.util.isDescendant(hadFocus, this.lastMousedownTarget, true) ||
2862
+ isElementDescendantOfExtension(this.base.extensions, this.lastMousedownTarget))) {
2810
2863
  toFocus = hadFocus;
2811
2864
  }
2812
2865
 
@@ -2822,10 +2875,9 @@ MediumEditor.extensions = {};
2822
2875
  }, this);
2823
2876
  }
2824
2877
 
2825
- // Check if the target is external (not part of the editor, toolbar, or anchorpreview)
2878
+ // Check if the target is external (not part of the editor, toolbar, or any other extension)
2826
2879
  var externalEvent = !MediumEditor.util.isDescendant(hadFocus, target, true) &&
2827
- !MediumEditor.util.isDescendant(toolbarEl, target, true) &&
2828
- !MediumEditor.util.isDescendant(previewEl, target, true);
2880
+ !isElementDescendantOfExtension(this.base.extensions, target);
2829
2881
 
2830
2882
  if (toFocus !== hadFocus) {
2831
2883
  // If element has focus, and focus is going outside of editor
@@ -3310,6 +3362,14 @@ MediumEditor.extensions = {};
3310
3362
  contentDefault: '<b>image</b>',
3311
3363
  contentFA: '<i class="fa fa-picture-o"></i>'
3312
3364
  },
3365
+ 'html': {
3366
+ name: 'html',
3367
+ action: 'html',
3368
+ aria: 'evaluate html',
3369
+ tagNames: ['iframe', 'object'],
3370
+ contentDefault: '<b>html</b>',
3371
+ contentFA: '<i class="fa fa-code"></i>'
3372
+ },
3313
3373
  'orderedlist': {
3314
3374
  name: 'orderedlist',
3315
3375
  action: 'insertorderedlist',
@@ -3471,6 +3531,7 @@ MediumEditor.extensions = {};
3471
3531
  };
3472
3532
 
3473
3533
  })();
3534
+
3474
3535
  (function () {
3475
3536
  'use strict';
3476
3537
 
@@ -3703,8 +3764,8 @@ MediumEditor.extensions = {};
3703
3764
  // figure out how to deprecate? also consider `fa-` icon default implcations.
3704
3765
  template.push(
3705
3766
  '<div class="medium-editor-toolbar-form-row">',
3706
- '<input type="checkbox" class="medium-editor-toolbar-anchor-target">',
3707
- '<label>',
3767
+ '<input type="checkbox" class="medium-editor-toolbar-anchor-target" id="medium-editor-toolbar-anchor-target-field-' + this.getEditorId() + '">',
3768
+ '<label for="medium-editor-toolbar-anchor-target-field-' + this.getEditorId() + '">',
3708
3769
  this.targetCheckboxText,
3709
3770
  '</label>',
3710
3771
  '</div>'
@@ -3824,19 +3885,61 @@ MediumEditor.extensions = {};
3824
3885
  this.base.checkSelection();
3825
3886
  },
3826
3887
 
3888
+ ensureEncodedUri: function (str) {
3889
+ return str === decodeURI(str) ? encodeURI(str) : str;
3890
+ },
3891
+
3892
+ ensureEncodedUriComponent: function (str) {
3893
+ return str === decodeURIComponent(str) ? encodeURIComponent(str) : str;
3894
+ },
3895
+
3896
+ ensureEncodedParam: function (param) {
3897
+ var split = param.split('='),
3898
+ key = split[0],
3899
+ val = split[1];
3900
+
3901
+ return key + (val === undefined ? '' : '=' + this.ensureEncodedUriComponent(val));
3902
+ },
3903
+
3904
+ ensureEncodedQuery: function (queryString) {
3905
+ return queryString.split('&').map(this.ensureEncodedParam.bind(this)).join('&');
3906
+ },
3907
+
3827
3908
  checkLinkFormat: function (value) {
3828
3909
  // Matches any alphabetical characters followed by ://
3829
3910
  // Matches protocol relative "//"
3830
3911
  // Matches common external protocols "mailto:" "tel:" "maps:"
3831
- var urlSchemeRegex = /^([a-z]+:)?\/\/|^(mailto|tel|maps):/i,
3832
- // var te is a regex for checking if the string is a telephone number
3833
- telRegex = /^\+?\s?\(?(?:\d\s?\-?\)?){3,20}$/;
3912
+ // Matches relative hash link, begins with "#"
3913
+ var urlSchemeRegex = /^([a-z]+:)?\/\/|^(mailto|tel|maps):|^\#/i,
3914
+ hasScheme = urlSchemeRegex.test(value),
3915
+ scheme = '',
3916
+ // telRegex is a regex for checking if the string is a telephone number
3917
+ telRegex = /^\+?\s?\(?(?:\d\s?\-?\)?){3,20}$/,
3918
+ urlParts = value.match(/^(.*?)(?:\?(.*?))?(?:#(.*))?$/),
3919
+ path = urlParts[1],
3920
+ query = urlParts[2],
3921
+ fragment = urlParts[3];
3922
+
3834
3923
  if (telRegex.test(value)) {
3835
3924
  return 'tel:' + value;
3836
- } else {
3837
- // Check for URL scheme and default to http:// if none found
3838
- return (urlSchemeRegex.test(value) ? '' : 'http://') + encodeURI(value);
3839
3925
  }
3926
+
3927
+ if (!hasScheme) {
3928
+ var host = path.split('/')[0];
3929
+ // if the host part of the path looks like a hostname
3930
+ if (host.match(/.+(\.|:).+/) || host === 'localhost') {
3931
+ scheme = 'http://';
3932
+ }
3933
+ }
3934
+
3935
+ return scheme +
3936
+ // Ensure path is encoded
3937
+ this.ensureEncodedUri(path) +
3938
+ // Ensure query is encoded
3939
+ (query === undefined ? '' : '?' + this.ensureEncodedQuery(query)) +
3940
+ // Include fragment unencoded as encodeUriComponent is too
3941
+ // heavy handed for the many characters allowed in a fragment
3942
+ (fragment === undefined ? '' : '#' + fragment);
3840
3943
  },
3841
3944
 
3842
3945
  doFormCancel: function () {
@@ -3948,6 +4051,11 @@ MediumEditor.extensions = {};
3948
4051
  */
3949
4052
  showWhenToolbarIsVisible: false,
3950
4053
 
4054
+ /* showOnEmptyLinks: [boolean]
4055
+ * determines whether the anchor tag preview shows up on links with href="" or href="#something"
4056
+ */
4057
+ showOnEmptyLinks: true,
4058
+
3951
4059
  init: function () {
3952
4060
  this.anchorPreview = this.createPreview();
3953
4061
 
@@ -3956,6 +4064,11 @@ MediumEditor.extensions = {};
3956
4064
  this.attachToEditables();
3957
4065
  },
3958
4066
 
4067
+ getInteractionElements: function () {
4068
+ return this.getPreviewElement();
4069
+ },
4070
+
4071
+ // TODO: Remove this function in 6.0.0
3959
4072
  getPreviewElement: function () {
3960
4073
  return this.anchorPreview;
3961
4074
  },
@@ -3988,7 +4101,9 @@ MediumEditor.extensions = {};
3988
4101
  },
3989
4102
 
3990
4103
  hidePreview: function () {
3991
- this.anchorPreview.classList.remove('medium-editor-anchor-preview-active');
4104
+ if (this.anchorPreview) {
4105
+ this.anchorPreview.classList.remove('medium-editor-anchor-preview-active');
4106
+ }
3992
4107
  this.activeAnchor = null;
3993
4108
  },
3994
4109
 
@@ -4020,13 +4135,15 @@ MediumEditor.extensions = {};
4020
4135
 
4021
4136
  positionPreview: function (activeAnchor) {
4022
4137
  activeAnchor = activeAnchor || this.activeAnchor;
4023
- var buttonHeight = this.anchorPreview.offsetHeight,
4138
+ var containerWidth = this.window.innerWidth,
4139
+ buttonHeight = this.anchorPreview.offsetHeight,
4024
4140
  boundary = activeAnchor.getBoundingClientRect(),
4025
- middleBoundary = (boundary.left + boundary.right) / 2,
4026
4141
  diffLeft = this.diffLeft,
4027
4142
  diffTop = this.diffTop,
4028
- halfOffsetWidth,
4029
- defaultLeft;
4143
+ elementsContainer = this.getEditorOption('elementsContainer'),
4144
+ elementsContainerAbsolute = ['absolute', 'fixed'].indexOf(window.getComputedStyle(elementsContainer).getPropertyValue('position')) > -1,
4145
+ relativeBoundary = {},
4146
+ halfOffsetWidth, defaultLeft, middleBoundary, elementsContainerBoundary, top;
4030
4147
 
4031
4148
  halfOffsetWidth = this.anchorPreview.offsetWidth / 2;
4032
4149
  var toolbarExtension = this.base.getExtensionByName('toolbar');
@@ -4036,12 +4153,35 @@ MediumEditor.extensions = {};
4036
4153
  }
4037
4154
  defaultLeft = diffLeft - halfOffsetWidth;
4038
4155
 
4039
- this.anchorPreview.style.top = Math.round(buttonHeight + boundary.bottom - diffTop + this.window.pageYOffset - this.anchorPreview.offsetHeight) + 'px';
4156
+ // If container element is absolute / fixed, recalculate boundaries to be relative to the container
4157
+ if (elementsContainerAbsolute) {
4158
+ elementsContainerBoundary = elementsContainer.getBoundingClientRect();
4159
+ ['top', 'left'].forEach(function (key) {
4160
+ relativeBoundary[key] = boundary[key] - elementsContainerBoundary[key];
4161
+ });
4162
+
4163
+ relativeBoundary.width = boundary.width;
4164
+ relativeBoundary.height = boundary.height;
4165
+ boundary = relativeBoundary;
4166
+
4167
+ containerWidth = elementsContainerBoundary.width;
4168
+
4169
+ // Adjust top position according to container scroll position
4170
+ top = elementsContainer.scrollTop;
4171
+ } else {
4172
+ // Adjust top position according to window scroll position
4173
+ top = this.window.pageYOffset;
4174
+ }
4175
+
4176
+ middleBoundary = boundary.left + boundary.width / 2;
4177
+ top += buttonHeight + boundary.top + boundary.height - diffTop - this.anchorPreview.offsetHeight;
4178
+
4179
+ this.anchorPreview.style.top = Math.round(top) + 'px';
4040
4180
  this.anchorPreview.style.right = 'initial';
4041
4181
  if (middleBoundary < halfOffsetWidth) {
4042
4182
  this.anchorPreview.style.left = defaultLeft + halfOffsetWidth + 'px';
4043
4183
  this.anchorPreview.style.right = 'initial';
4044
- } else if ((this.window.innerWidth - middleBoundary) < halfOffsetWidth) {
4184
+ } else if ((containerWidth - middleBoundary) < halfOffsetWidth) {
4045
4185
  this.anchorPreview.style.left = 'auto';
4046
4186
  this.anchorPreview.style.right = 0;
4047
4187
  } else {
@@ -4077,7 +4217,7 @@ MediumEditor.extensions = {};
4077
4217
  this.base.delay(function () {
4078
4218
  if (activeAnchor) {
4079
4219
  var opts = {
4080
- url: activeAnchor.attributes.href.value,
4220
+ value: activeAnchor.attributes.href.value,
4081
4221
  target: activeAnchor.getAttribute('target'),
4082
4222
  buttonClass: activeAnchor.getAttribute('class')
4083
4223
  };
@@ -4106,7 +4246,8 @@ MediumEditor.extensions = {};
4106
4246
  // Detect empty href attributes
4107
4247
  // The browser will make href="" or href="#top"
4108
4248
  // into absolute urls when accessed as event.target.href, so check the html
4109
- if (!/href=["']\S+["']/.test(target.outerHTML) || /href=["']#\S+["']/.test(target.outerHTML)) {
4249
+ if (!this.showOnEmptyLinks &&
4250
+ (!/href=["']\S+["']/.test(target.outerHTML) || /href=["']#\S+["']/.test(target.outerHTML))) {
4110
4251
  return true;
4111
4252
  }
4112
4253
 
@@ -4200,7 +4341,8 @@ MediumEditor.extensions = {};
4200
4341
  var WHITESPACE_CHARS,
4201
4342
  KNOWN_TLDS_FRAGMENT,
4202
4343
  LINK_REGEXP_TEXT,
4203
- KNOWN_TLDS_REGEXP;
4344
+ KNOWN_TLDS_REGEXP,
4345
+ LINK_REGEXP;
4204
4346
 
4205
4347
  WHITESPACE_CHARS = [' ', '\t', '\n', '\r', '\u00A0', '\u2000', '\u2001', '\u2002', '\u2003',
4206
4348
  '\u2028', '\u2029'];
@@ -4222,6 +4364,8 @@ MediumEditor.extensions = {};
4222
4364
 
4223
4365
  KNOWN_TLDS_REGEXP = new RegExp('^(' + KNOWN_TLDS_FRAGMENT + ')$', 'i');
4224
4366
 
4367
+ LINK_REGEXP = new RegExp(LINK_REGEXP_TEXT, 'gi');
4368
+
4225
4369
  function nodeIsNotInsideAnchorTag(node) {
4226
4370
  return !MediumEditor.util.getClosestTag(node, 'a');
4227
4371
  }
@@ -4403,12 +4547,11 @@ MediumEditor.extensions = {};
4403
4547
  },
4404
4548
 
4405
4549
  findLinkableText: function (contenteditable) {
4406
- var linkRegExp = new RegExp(LINK_REGEXP_TEXT, 'gi'),
4407
- textContent = contenteditable.textContent,
4550
+ var textContent = contenteditable.textContent,
4408
4551
  match = null,
4409
4552
  matches = [];
4410
4553
 
4411
- while ((match = linkRegExp.exec(textContent)) !== null) {
4554
+ while ((match = LINK_REGEXP.exec(textContent)) !== null) {
4412
4555
  var matchOk = true,
4413
4556
  matchEnd = match.index + match[0].length;
4414
4557
  // If the regexp detected something as a link that has text immediately preceding/following it, bail out.
@@ -5027,13 +5170,13 @@ MediumEditor.extensions = {};
5027
5170
  [new RegExp(/<br class="Apple-interchange-newline">/g), '<br>'],
5028
5171
 
5029
5172
  // replace google docs italics+bold with a span to be replaced once the html is inserted
5030
- [new RegExp(/<span[^>]*(font-style:italic;font-weight:bold|font-weight:bold;font-style:italic)[^>]*>/gi), '<span class="replace-with italic bold">'],
5173
+ [new RegExp(/<span[^>]*(font-style:italic;font-weight:(bold|700)|font-weight:(bold|700);font-style:italic)[^>]*>/gi), '<span class="replace-with italic bold">'],
5031
5174
 
5032
5175
  // replace google docs italics with a span to be replaced once the html is inserted
5033
5176
  [new RegExp(/<span[^>]*font-style:italic[^>]*>/gi), '<span class="replace-with italic">'],
5034
5177
 
5035
5178
  //[replace google docs bolds with a span to be replaced once the html is inserted
5036
- [new RegExp(/<span[^>]*font-weight:bold[^>]*>/gi), '<span class="replace-with bold">'],
5179
+ [new RegExp(/<span[^>]*font-weight:(bold|700)[^>]*>/gi), '<span class="replace-with bold">'],
5037
5180
 
5038
5181
  // replace manually entered b/i/a tags with real ones
5039
5182
  [new RegExp(/&lt;(\/?)(i|b|a)&gt;/gi), '<$1$2>'],
@@ -5129,15 +5272,31 @@ MediumEditor.extensions = {};
5129
5272
  */
5130
5273
  cleanTags: ['meta'],
5131
5274
 
5275
+ /* unwrapTags: [Array]
5276
+ * list of element tag names to unwrap (remove the element tag but retain its child elements)
5277
+ * during paste when __cleanPastedHTML__ is `true` or when
5278
+ * calling `cleanPaste(text)` or `pasteHTML(html, options)` helper methods.
5279
+ */
5280
+ unwrapTags: [],
5281
+
5132
5282
  init: function () {
5133
5283
  MediumEditor.Extension.prototype.init.apply(this, arguments);
5134
5284
 
5135
5285
  if (this.forcePlainText || this.cleanPastedHTML) {
5136
- this.subscribe('editablePaste', this.handlePaste.bind(this));
5137
5286
  this.subscribe('editableKeydown', this.handleKeydown.bind(this));
5287
+ // We need access to the full event data in paste
5288
+ // so we can't use the editablePaste event here
5289
+ this.getEditorElements().forEach(function (element) {
5290
+ this.on(element, 'paste', this.handlePaste.bind(this));
5291
+ }, this);
5292
+ this.subscribe('addElement', this.handleAddElement.bind(this));
5138
5293
  }
5139
5294
  },
5140
5295
 
5296
+ handleAddElement: function (event, editable) {
5297
+ this.on(editable, 'paste', this.handlePaste.bind(this));
5298
+ },
5299
+
5141
5300
  destroy: function () {
5142
5301
  // Make sure pastebin is destroyed in case it's still around for some reason
5143
5302
  if (this.forcePlainText || this.cleanPastedHTML) {
@@ -5214,6 +5373,12 @@ MediumEditor.extensions = {};
5214
5373
  event.preventDefault();
5215
5374
  this.removePasteBin();
5216
5375
  this.doPaste(pastedHTML, pastedPlain, editable);
5376
+
5377
+ // The event handling code listens for paste on the editable element
5378
+ // in order to trigger the editablePaste event. Since this paste event
5379
+ // is happening on the pastebin, the event handling code never knows about it
5380
+ // So, we have to trigger editablePaste manually
5381
+ this.trigger('editablePaste', { currentTarget: editable, target: editable }, editable);
5217
5382
  return;
5218
5383
  }
5219
5384
 
@@ -5231,6 +5396,12 @@ MediumEditor.extensions = {};
5231
5396
 
5232
5397
  // Handle the paste with the html from the paste bin
5233
5398
  this.doPaste(pastedHTML, pastedPlain, editable);
5399
+
5400
+ // The event handling code listens for paste on the editable element
5401
+ // in order to trigger the editablePaste event. Since this paste event
5402
+ // is happening on the pastebin, the event handling code never knows about it
5403
+ // So, we have to trigger editablePaste manually
5404
+ this.trigger('editablePaste', { currentTarget: editable, target: editable }, editable);
5234
5405
  }.bind(this), 0);
5235
5406
  },
5236
5407
 
@@ -5391,7 +5562,8 @@ MediumEditor.extensions = {};
5391
5562
  pasteHTML: function (html, options) {
5392
5563
  options = MediumEditor.util.defaults({}, options, {
5393
5564
  cleanAttrs: this.cleanAttrs,
5394
- cleanTags: this.cleanTags
5565
+ cleanTags: this.cleanTags,
5566
+ unwrapTags: this.unwrapTags
5395
5567
  });
5396
5568
 
5397
5569
  var elList, workEl, i, fragmentBody, pasteBlock = this.document.createDocumentFragment();
@@ -5413,6 +5585,7 @@ MediumEditor.extensions = {};
5413
5585
 
5414
5586
  MediumEditor.util.cleanupAttrs(workEl, options.cleanAttrs);
5415
5587
  MediumEditor.util.cleanupTags(workEl, options.cleanTags);
5588
+ MediumEditor.util.unwrapTags(workEl, options.unwrapTags);
5416
5589
  }
5417
5590
 
5418
5591
  MediumEditor.util.insertHTMLCommand(this.document, fragmentBody.innerHTML.replace(/&nbsp;/g, ' '));
@@ -5523,37 +5696,61 @@ MediumEditor.extensions = {};
5523
5696
  },
5524
5697
 
5525
5698
  initPlaceholders: function () {
5526
- this.getEditorElements().forEach(function (el) {
5527
- if (!el.getAttribute('data-placeholder')) {
5528
- el.setAttribute('data-placeholder', this.text);
5529
- }
5530
- this.updatePlaceholder(el);
5531
- }, this);
5699
+ this.getEditorElements().forEach(this.initElement, this);
5700
+ },
5701
+
5702
+ handleAddElement: function (event, editable) {
5703
+ this.initElement(editable);
5704
+ },
5705
+
5706
+ initElement: function (el) {
5707
+ if (!el.getAttribute('data-placeholder')) {
5708
+ el.setAttribute('data-placeholder', this.text);
5709
+ }
5710
+ this.updatePlaceholder(el);
5532
5711
  },
5533
5712
 
5534
5713
  destroy: function () {
5535
- this.getEditorElements().forEach(function (el) {
5536
- if (el.getAttribute('data-placeholder') === this.text) {
5537
- el.removeAttribute('data-placeholder');
5538
- }
5539
- }, this);
5714
+ this.getEditorElements().forEach(this.cleanupElement, this);
5715
+ },
5716
+
5717
+ handleRemoveElement: function (event, editable) {
5718
+ this.cleanupElement(editable);
5719
+ },
5720
+
5721
+ cleanupElement: function (el) {
5722
+ if (el.getAttribute('data-placeholder') === this.text) {
5723
+ el.removeAttribute('data-placeholder');
5724
+ }
5540
5725
  },
5541
5726
 
5542
5727
  showPlaceholder: function (el) {
5543
5728
  if (el) {
5544
- el.classList.add('medium-editor-placeholder');
5729
+ // https://github.com/yabwe/medium-editor/issues/234
5730
+ // In firefox, styling the placeholder with an absolutely positioned
5731
+ // pseudo element causes the cursor to appear in a bad location
5732
+ // when the element is completely empty, so apply a different class to
5733
+ // style it with a relatively positioned pseudo element
5734
+ if (MediumEditor.util.isFF && el.childNodes.length === 0) {
5735
+ el.classList.add('medium-editor-placeholder-relative');
5736
+ el.classList.remove('medium-editor-placeholder');
5737
+ } else {
5738
+ el.classList.add('medium-editor-placeholder');
5739
+ el.classList.remove('medium-editor-placeholder-relative');
5740
+ }
5545
5741
  }
5546
5742
  },
5547
5743
 
5548
5744
  hidePlaceholder: function (el) {
5549
5745
  if (el) {
5550
5746
  el.classList.remove('medium-editor-placeholder');
5747
+ el.classList.remove('medium-editor-placeholder-relative');
5551
5748
  }
5552
5749
  },
5553
5750
 
5554
5751
  updatePlaceholder: function (el, dontShow) {
5555
5752
  // If the element has content, hide the placeholder
5556
- if (el.querySelector('img, blockquote, ul, ol') || (el.textContent.replace(/^\s+|\s+$/g, '') !== '')) {
5753
+ if (el.querySelector('img, blockquote, ul, ol, table') || (el.textContent.replace(/^\s+|\s+$/g, '') !== '')) {
5557
5754
  return this.hidePlaceholder(el);
5558
5755
  }
5559
5756
 
@@ -5573,6 +5770,10 @@ MediumEditor.extensions = {};
5573
5770
 
5574
5771
  // When the editor loses focus, check if the placeholder should be visible
5575
5772
  this.subscribe('blur', this.handleBlur.bind(this));
5773
+
5774
+ // Need to know when elements are added/removed from the editor
5775
+ this.subscribe('addElement', this.handleAddElement.bind(this));
5776
+ this.subscribe('removeElement', this.handleRemoveElement.bind(this));
5576
5777
  },
5577
5778
 
5578
5779
  handleInput: function (event, element) {
@@ -5789,6 +5990,10 @@ MediumEditor.extensions = {};
5789
5990
 
5790
5991
  // Toolbar accessors
5791
5992
 
5993
+ getInteractionElements: function () {
5994
+ return this.getToolbarElement();
5995
+ },
5996
+
5792
5997
  getToolbarElement: function () {
5793
5998
  if (!this.toolbar) {
5794
5999
  this.toolbar = this.createToolbar();
@@ -6212,35 +6417,66 @@ MediumEditor.extensions = {};
6212
6417
  }
6213
6418
  }
6214
6419
 
6215
- var windowWidth = this.window.innerWidth,
6216
- middleBoundary = (boundary.left + boundary.right) / 2,
6420
+ var containerWidth = this.window.innerWidth,
6217
6421
  toolbarElement = this.getToolbarElement(),
6218
6422
  toolbarHeight = toolbarElement.offsetHeight,
6219
6423
  toolbarWidth = toolbarElement.offsetWidth,
6220
6424
  halfOffsetWidth = toolbarWidth / 2,
6221
6425
  buttonHeight = 50,
6222
- defaultLeft = this.diffLeft - halfOffsetWidth;
6426
+ defaultLeft = this.diffLeft - halfOffsetWidth,
6427
+ elementsContainer = this.getEditorOption('elementsContainer'),
6428
+ elementsContainerAbsolute = ['absolute', 'fixed'].indexOf(window.getComputedStyle(elementsContainer).getPropertyValue('position')) > -1,
6429
+ positions = {},
6430
+ relativeBoundary = {},
6431
+ middleBoundary, elementsContainerBoundary;
6432
+
6433
+ // If container element is absolute / fixed, recalculate boundaries to be relative to the container
6434
+ if (elementsContainerAbsolute) {
6435
+ elementsContainerBoundary = elementsContainer.getBoundingClientRect();
6436
+ ['top', 'left'].forEach(function (key) {
6437
+ relativeBoundary[key] = boundary[key] - elementsContainerBoundary[key];
6438
+ });
6439
+
6440
+ relativeBoundary.width = boundary.width;
6441
+ relativeBoundary.height = boundary.height;
6442
+ boundary = relativeBoundary;
6443
+
6444
+ containerWidth = elementsContainerBoundary.width;
6445
+
6446
+ // Adjust top position according to container scroll position
6447
+ positions.top = elementsContainer.scrollTop;
6448
+ } else {
6449
+ // Adjust top position according to window scroll position
6450
+ positions.top = this.window.pageYOffset;
6451
+ }
6452
+
6453
+ middleBoundary = boundary.left + boundary.width / 2;
6454
+ positions.top += boundary.top - toolbarHeight;
6223
6455
 
6224
6456
  if (boundary.top < buttonHeight) {
6225
6457
  toolbarElement.classList.add('medium-toolbar-arrow-over');
6226
6458
  toolbarElement.classList.remove('medium-toolbar-arrow-under');
6227
- toolbarElement.style.top = buttonHeight + boundary.bottom - this.diffTop + this.window.pageYOffset - toolbarHeight + 'px';
6459
+ positions.top += buttonHeight + boundary.height - this.diffTop;
6228
6460
  } else {
6229
6461
  toolbarElement.classList.add('medium-toolbar-arrow-under');
6230
6462
  toolbarElement.classList.remove('medium-toolbar-arrow-over');
6231
- toolbarElement.style.top = boundary.top + this.diffTop + this.window.pageYOffset - toolbarHeight + 'px';
6463
+ positions.top += this.diffTop;
6232
6464
  }
6233
6465
 
6234
6466
  if (middleBoundary < halfOffsetWidth) {
6235
- toolbarElement.style.left = defaultLeft + halfOffsetWidth + 'px';
6236
- toolbarElement.style.right = 'initial';
6237
- } else if ((windowWidth - middleBoundary) < halfOffsetWidth) {
6238
- toolbarElement.style.left = 'auto';
6239
- toolbarElement.style.right = 0;
6467
+ positions.left = defaultLeft + halfOffsetWidth;
6468
+ positions.right = 'initial';
6469
+ } else if ((containerWidth - middleBoundary) < halfOffsetWidth) {
6470
+ positions.left = 'auto';
6471
+ positions.right = 0;
6240
6472
  } else {
6241
- toolbarElement.style.left = defaultLeft + middleBoundary + 'px';
6242
- toolbarElement.style.right = 'initial';
6473
+ positions.left = defaultLeft + middleBoundary;
6474
+ positions.right = 'initial';
6243
6475
  }
6476
+
6477
+ ['top', 'left', 'right'].forEach(function (key) {
6478
+ toolbarElement.style[key] = positions[key] + (isNaN(positions[key]) ? '' : 'px');
6479
+ });
6244
6480
  }
6245
6481
  });
6246
6482
 
@@ -6447,6 +6683,31 @@ MediumEditor.extensions = {};
6447
6683
  // then pressing backspace key should change the <blockquote> to a <p> tag
6448
6684
  event.preventDefault();
6449
6685
  MediumEditor.util.execFormatBlock(this.options.ownerDocument, 'p');
6686
+ } else if (MediumEditor.util.isKey(event, MediumEditor.util.keyCode.ENTER) &&
6687
+ (MediumEditor.util.getClosestTag(node, 'blockquote') !== false) &&
6688
+ MediumEditor.selection.getCaretOffsets(node).right === 0) {
6689
+
6690
+ // when cursor is at the end of <blockquote>,
6691
+ // then pressing enter key should create <p> tag, not <blockquote>
6692
+ p = this.options.ownerDocument.createElement('p');
6693
+ p.innerHTML = '<br>';
6694
+ node.parentElement.insertBefore(p, node.nextSibling);
6695
+
6696
+ // move the cursor into the new paragraph
6697
+ MediumEditor.selection.moveCursor(this.options.ownerDocument, p);
6698
+
6699
+ event.preventDefault();
6700
+ } else if (MediumEditor.util.isKey(event, MediumEditor.util.keyCode.BACKSPACE) &&
6701
+ MediumEditor.util.isMediumEditorElement(node.parentElement) &&
6702
+ !node.previousElementSibling &&
6703
+ node.nextElementSibling &&
6704
+ isEmpty.test(node.innerHTML)) {
6705
+
6706
+ // when cursor is in the first element, it's empty and user presses backspace,
6707
+ // do delete action instead to get rid of the first element and move caret to 2nd
6708
+ event.preventDefault();
6709
+ MediumEditor.selection.moveCursor(this.options.ownerDocument, node.nextSibling);
6710
+ node.parentElement.removeChild(node);
6450
6711
  }
6451
6712
  }
6452
6713
 
@@ -6642,17 +6903,17 @@ MediumEditor.extensions = {};
6642
6903
  return !this.options.extensions['imageDragging'];
6643
6904
  }
6644
6905
 
6645
- function createContentEditable(textarea, id, doc) {
6646
- var div = doc.createElement('div'),
6906
+ function createContentEditable(textarea) {
6907
+ var div = this.options.ownerDocument.createElement('div'),
6647
6908
  now = Date.now(),
6648
- uniqueId = 'medium-editor-' + now + '-' + id,
6909
+ uniqueId = 'medium-editor-' + now,
6649
6910
  atts = textarea.attributes;
6650
6911
 
6651
6912
  // Some browsers can move pretty fast, since we're using a timestamp
6652
6913
  // to make a unique-id, ensure that the id is actually unique on the page
6653
- while (doc.getElementById(uniqueId)) {
6914
+ while (this.options.ownerDocument.getElementById(uniqueId)) {
6654
6915
  now++;
6655
- uniqueId = 'medium-editor-' + now + '-' + id;
6916
+ uniqueId = 'medium-editor-' + now;
6656
6917
  }
6657
6918
 
6658
6919
  div.className = textarea.className;
@@ -6669,6 +6930,16 @@ MediumEditor.extensions = {};
6669
6930
  }
6670
6931
  }
6671
6932
 
6933
+ // If textarea has a form, listen for reset on the form to clear
6934
+ // the content of the created div
6935
+ if (textarea.form) {
6936
+ this.on(textarea.form, 'reset', function (event) {
6937
+ if (!event.defaultPrevented) {
6938
+ this.resetContent(this.options.ownerDocument.getElementById(uniqueId));
6939
+ }
6940
+ }.bind(this));
6941
+ }
6942
+
6672
6943
  textarea.classList.add('medium-editor-hidden');
6673
6944
  textarea.parentNode.insertBefore(
6674
6945
  div,
@@ -6678,10 +6949,10 @@ MediumEditor.extensions = {};
6678
6949
  return div;
6679
6950
  }
6680
6951
 
6681
- function initElement(element, id) {
6952
+ function initElement(element, editorId) {
6682
6953
  if (!element.getAttribute('data-medium-editor-element')) {
6683
6954
  if (element.nodeName.toLowerCase() === 'textarea') {
6684
- element = createContentEditable(element, id, this.options.ownerDocument);
6955
+ element = createContentEditable.call(this, element);
6685
6956
 
6686
6957
  // Make sure we only attach to editableInput once for <textarea> elements
6687
6958
  if (!this.instanceHandleEditableInput) {
@@ -6709,10 +6980,18 @@ MediumEditor.extensions = {};
6709
6980
  this.on(element, 'keyup', handleKeyup.bind(this));
6710
6981
  }
6711
6982
 
6983
+ var elementId = MediumEditor.util.guid();
6984
+
6712
6985
  element.setAttribute('data-medium-editor-element', true);
6986
+ element.classList.add('medium-editor-element');
6713
6987
  element.setAttribute('role', 'textbox');
6714
6988
  element.setAttribute('aria-multiline', true);
6715
- element.setAttribute('medium-editor-index', MediumEditor.util.guid());
6989
+ element.setAttribute('data-medium-editor-editor-index', editorId);
6990
+ // TODO: Merge data-medium-editor-element and medium-editor-index attributes for 6.0.0
6991
+ // medium-editor-index is not named correctly anymore and can be re-purposed to signify
6992
+ // whether the element has been initialized or not
6993
+ element.setAttribute('medium-editor-index', elementId);
6994
+ initialContent[elementId] = element.innerHTML;
6716
6995
 
6717
6996
  this.events.attachAllEventsToElement(element);
6718
6997
  }
@@ -6870,6 +7149,11 @@ MediumEditor.extensions = {};
6870
7149
  return this.options.ownerDocument.execCommand('insertImage', false, src);
6871
7150
  }
6872
7151
 
7152
+ if (action === 'html') {
7153
+ var html = this.options.contentWindow.getSelection().toString().trim();
7154
+ return MediumEditor.util.insertHTMLCommand(this.options.ownerDocument, html);
7155
+ }
7156
+
6873
7157
  /* Issue: https://github.com/yabwe/medium-editor/issues/595
6874
7158
  * If the action is to justify the text */
6875
7159
  if (justifyAction.exec(action)) {
@@ -6931,6 +7215,8 @@ MediumEditor.extensions = {};
6931
7215
  }
6932
7216
  }
6933
7217
 
7218
+ var initialContent = {};
7219
+
6934
7220
  MediumEditor.prototype = {
6935
7221
  // NOT DOCUMENTED - exposed for backwards compatability
6936
7222
  init: function (elements, options) {
@@ -6949,6 +7235,7 @@ MediumEditor.extensions = {};
6949
7235
  return;
6950
7236
  }
6951
7237
 
7238
+ addToEditors.call(this, this.options.contentWindow);
6952
7239
  this.events = new MediumEditor.Events(this);
6953
7240
  this.elements = [];
6954
7241
 
@@ -6959,7 +7246,6 @@ MediumEditor.extensions = {};
6959
7246
  }
6960
7247
 
6961
7248
  this.isActive = true;
6962
- addToEditors.call(this, this.options.contentWindow);
6963
7249
 
6964
7250
  // Call initialization helpers
6965
7251
  initExtensions.call(this);
@@ -6991,9 +7277,11 @@ MediumEditor.extensions = {};
6991
7277
  element.removeAttribute('contentEditable');
6992
7278
  element.removeAttribute('spellcheck');
6993
7279
  element.removeAttribute('data-medium-editor-element');
7280
+ element.classList.remove('medium-editor-element');
6994
7281
  element.removeAttribute('role');
6995
7282
  element.removeAttribute('aria-multiline');
6996
7283
  element.removeAttribute('medium-editor-index');
7284
+ element.removeAttribute('data-medium-editor-editor-index');
6997
7285
 
6998
7286
  // Remove any elements created for textareas
6999
7287
  if (element.getAttribute('medium-editor-textarea-id')) {
@@ -7452,11 +7740,38 @@ MediumEditor.extensions = {};
7452
7740
  }
7453
7741
  },
7454
7742
 
7743
+ getContent: function (index) {
7744
+ index = index || 0;
7745
+
7746
+ if (this.elements[index]) {
7747
+ return this.elements[index].innerHTML.trim();
7748
+ }
7749
+ return null;
7750
+ },
7751
+
7455
7752
  checkContentChanged: function (editable) {
7456
7753
  editable = editable || MediumEditor.selection.getSelectionElement(this.options.contentWindow);
7457
7754
  this.events.updateInput(editable, { target: editable, currentTarget: editable });
7458
7755
  },
7459
7756
 
7757
+ resetContent: function (element) {
7758
+ // For all elements that exist in the this.elements array, we can assume:
7759
+ // - Its initial content has been set in the initialContent object
7760
+ // - It has a medium-editor-index attribute which is the key value in the initialContent object
7761
+
7762
+ if (element) {
7763
+ var index = this.elements.indexOf(element);
7764
+ if (index !== -1) {
7765
+ this.setContent(initialContent[element.getAttribute('medium-editor-index')], index);
7766
+ }
7767
+ return;
7768
+ }
7769
+
7770
+ this.elements.forEach(function (el, idx) {
7771
+ this.setContent(initialContent[el.getAttribute('medium-editor-index')], idx);
7772
+ }, this);
7773
+ },
7774
+
7460
7775
  addElements: function (selector) {
7461
7776
  // Convert elements into an array
7462
7777
  var elements = createElementsArray(selector, this.options.ownerDocument, true);
@@ -7468,10 +7783,13 @@ MediumEditor.extensions = {};
7468
7783
 
7469
7784
  elements.forEach(function (element) {
7470
7785
  // Initialize all new elements (we check that in those functions don't worry)
7471
- element = initElement.call(this, element);
7786
+ element = initElement.call(this, element, this.id);
7472
7787
 
7473
7788
  // Add new elements to our internal elements array
7474
7789
  this.elements.push(element);
7790
+
7791
+ // Trigger event so extensions can know when an element has been added
7792
+ this.trigger('addElement', { target: element, currentTarget: element }, element);
7475
7793
  }, this);
7476
7794
  },
7477
7795
 
@@ -7494,12 +7812,23 @@ MediumEditor.extensions = {};
7494
7812
  if (element.getAttribute('medium-editor-textarea-id')) {
7495
7813
  cleanupTextareaElement(element);
7496
7814
  }
7815
+ // Trigger event so extensions can clean-up elements that are being removed
7816
+ this.trigger('removeElement', { target: element, currentTarget: element }, element);
7497
7817
  return false;
7498
7818
  }
7499
7819
  return true;
7500
7820
  }, this);
7501
7821
  }
7502
7822
  };
7823
+
7824
+ MediumEditor.getEditorFromElement = function (element) {
7825
+ var index = element.getAttribute('data-medium-editor-editor-index'),
7826
+ win = element && element.ownerDocument && (element.ownerDocument.defaultView || element.ownerDocument.parentWindow);
7827
+ if (win && win._mediumEditors && win._mediumEditors[index]) {
7828
+ return win._mediumEditors[index];
7829
+ }
7830
+ return null;
7831
+ };
7503
7832
  }());
7504
7833
 
7505
7834
  (function () {
@@ -7540,7 +7869,7 @@ MediumEditor.parseVersionString = function (release) {
7540
7869
 
7541
7870
  MediumEditor.version = MediumEditor.parseVersionString.call(this, ({
7542
7871
  // grunt-bump looks for this:
7543
- 'version': '5.18.0'
7872
+ 'version': '5.23.1'
7544
7873
  }).version);
7545
7874
 
7546
7875
  return MediumEditor;