spree_emails 6.0.0.beta4 → 6.0.0.rc2

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 (172) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +30 -74
  3. data/Rakefile +23 -0
  4. data/app/mailers/spree/company_mailer.rb +4 -7
  5. data/app/mailers/spree/customer_mailer.rb +6 -8
  6. data/app/mailers/spree/digital_asset_mailer.rb +18 -11
  7. data/app/mailers/spree/fulfillment_mailer.rb +11 -7
  8. data/app/mailers/spree/newsletter_mailer.rb +1 -2
  9. data/app/mailers/spree/order_group_mailer.rb +16 -20
  10. data/app/mailers/spree/order_mailer.rb +15 -20
  11. data/app/mailers/spree/return_mailer.rb +10 -5
  12. data/app/mailers/spree/seller_mailer.rb +8 -13
  13. data/app/models/spree/emails/amount_line.rb +32 -0
  14. data/app/serializers/spree/emails/address_serializer.rb +6 -0
  15. data/app/serializers/spree/emails/amount_line_serializer.rb +13 -0
  16. data/app/serializers/spree/emails/applied_promotion_serializer.rb +7 -0
  17. data/app/serializers/spree/emails/customer_group_serializer.rb +6 -0
  18. data/app/serializers/spree/emails/customer_serializer.rb +19 -0
  19. data/app/serializers/spree/emails/delivery_method_serializer.rb +6 -0
  20. data/app/serializers/spree/emails/delivery_rate_serializer.rb +12 -0
  21. data/app/serializers/spree/emails/delivery_serializer.rb +6 -0
  22. data/app/serializers/spree/emails/fee_serializer.rb +7 -0
  23. data/app/serializers/spree/emails/freight_summary_serializer.rb +6 -0
  24. data/app/serializers/spree/emails/fulfillment_group_serializer.rb +25 -0
  25. data/app/serializers/spree/emails/fulfillment_serializer.rb +21 -0
  26. data/app/serializers/spree/emails/gift_card_serializer.rb +7 -0
  27. data/app/serializers/spree/emails/line_item_serializer.rb +24 -0
  28. data/app/serializers/spree/emails/market_serializer.rb +6 -0
  29. data/app/serializers/spree/emails/newsletter_subscriber_serializer.rb +6 -0
  30. data/app/serializers/spree/emails/option_value_serializer.rb +6 -0
  31. data/app/serializers/spree/emails/order_group_serializer.rb +50 -0
  32. data/app/serializers/spree/emails/order_serializer.rb +27 -0
  33. data/app/serializers/spree/emails/parcel_item_serializer.rb +36 -0
  34. data/app/serializers/spree/emails/payment_method_serializer.rb +6 -0
  35. data/app/serializers/spree/emails/payment_serializer.rb +11 -0
  36. data/app/serializers/spree/emails/purchase_summary_attributes.rb +41 -0
  37. data/app/serializers/spree/emails/purchased_item_attributes.rb +28 -0
  38. data/app/serializers/spree/emails/return_serializer.rb +19 -0
  39. data/app/serializers/spree/emails/stock_location_serializer.rb +6 -0
  40. data/app/services/spree/emails/samples/base.rb +79 -0
  41. data/app/services/spree/emails/samples/company_invitation.rb +19 -0
  42. data/app/services/spree/emails/samples/data_export.rb +11 -0
  43. data/app/services/spree/emails/samples/downloads.rb +28 -0
  44. data/app/services/spree/emails/samples/fulfillment.rb +33 -0
  45. data/app/services/spree/emails/samples/newsletter_confirmation.rb +11 -0
  46. data/app/services/spree/emails/samples/order.rb +22 -0
  47. data/app/services/spree/emails/samples/order_group.rb +22 -0
  48. data/app/services/spree/emails/samples/password_reset.rb +15 -0
  49. data/app/services/spree/emails/samples/payment_link.rb +17 -0
  50. data/app/services/spree/emails/samples/return.rb +29 -0
  51. data/app/subscribers/spree/order_email_subscriber.rb +2 -2
  52. data/app/subscribers/spree/order_group_email_subscriber.rb +1 -1
  53. data/app/subscribers/spree/return_email_subscriber.rb +2 -0
  54. data/app/views/spree/company_mailer/invitation_email.liquid +13 -0
  55. data/app/views/spree/customer_mailer/data_export_email.liquid +18 -0
  56. data/app/views/spree/customer_mailer/password_reset_email.liquid +14 -0
  57. data/app/views/spree/digital_asset_mailer/files_ready_email.liquid +23 -0
  58. data/app/views/spree/fulfillment_mailer/fulfilled_email.liquid +21 -0
  59. data/app/views/spree/newsletter_mailer/email_confirmation.liquid +13 -0
  60. data/app/views/spree/order_group_mailer/confirm_email.liquid +35 -0
  61. data/app/views/spree/order_group_mailer/store_owner_notification_email.liquid +11 -0
  62. data/app/views/spree/order_mailer/cancel_email.liquid +12 -0
  63. data/app/views/spree/order_mailer/confirm_email.liquid +12 -0
  64. data/app/views/spree/order_mailer/payment_link_email.liquid +12 -0
  65. data/app/views/spree/order_mailer/store_owner_notification_email.liquid +11 -0
  66. data/app/views/spree/return_mailer/refunded_email.liquid +19 -0
  67. data/app/views/spree/seller_mailer/approved_email.liquid +13 -0
  68. data/app/views/spree/seller_mailer/rejected_email.liquid +11 -0
  69. data/app/views/spree/seller_mailer/suspended_email.liquid +11 -0
  70. data/app/views/spree/shared/_fulfillment_group.liquid +25 -0
  71. data/app/views/spree/shared/_line_item.liquid +29 -0
  72. data/app/views/spree/shared/_order_summary.liquid +17 -0
  73. data/app/views/spree/shared/_purchase_totals.liquid +35 -0
  74. data/config/initializers/typelizer.rb +61 -0
  75. data/config/locales/ar.yml +40 -0
  76. data/config/locales/be.yml +37 -0
  77. data/config/locales/bg.yml +31 -0
  78. data/config/locales/ca.yml +35 -0
  79. data/config/locales/cs.yml +38 -0
  80. data/config/locales/da.yml +37 -0
  81. data/config/locales/de-CH.yml +11 -0
  82. data/config/locales/de.yml +38 -0
  83. data/config/locales/el.yml +37 -0
  84. data/config/locales/en.yml +0 -25
  85. data/config/locales/es-CL.yml +21 -0
  86. data/config/locales/es-EC.yml +22 -0
  87. data/config/locales/es-MX.yml +26 -0
  88. data/config/locales/es.yml +40 -0
  89. data/config/locales/et.yml +31 -0
  90. data/config/locales/fa.yml +37 -0
  91. data/config/locales/fi.yml +37 -0
  92. data/config/locales/fr.yml +38 -0
  93. data/config/locales/hu.yml +37 -0
  94. data/config/locales/id.yml +37 -0
  95. data/config/locales/it.yml +38 -0
  96. data/config/locales/ja.yml +36 -0
  97. data/config/locales/km.yml +37 -0
  98. data/config/locales/ko.yml +36 -0
  99. data/config/locales/ku.yml +37 -0
  100. data/config/locales/lt.yml +37 -0
  101. data/config/locales/lv.yml +39 -0
  102. data/config/locales/nb.yml +37 -0
  103. data/config/locales/ne.yml +37 -0
  104. data/config/locales/nl.yml +38 -0
  105. data/config/locales/pl.yml +39 -0
  106. data/config/locales/pt-BR.yml +34 -0
  107. data/config/locales/pt.yml +34 -0
  108. data/config/locales/ro.yml +37 -0
  109. data/config/locales/ru.yml +38 -0
  110. data/config/locales/sk.yml +31 -0
  111. data/config/locales/sl-SI.yml +31 -0
  112. data/config/locales/sv.yml +37 -0
  113. data/config/locales/th.yml +37 -0
  114. data/config/locales/tr.yml +38 -0
  115. data/config/locales/uk.yml +42 -0
  116. data/config/locales/vi.yml +35 -0
  117. data/config/locales/zh-CN.yml +38 -0
  118. data/config/locales/zh-TW.yml +40 -0
  119. data/lib/spree/emails/engine.rb +27 -3
  120. data/lib/spree/emails/previews/company_preview.rb +10 -0
  121. data/lib/spree/emails/previews/customer_preview.rb +4 -0
  122. data/lib/spree/emails/previews/digital_asset_preview.rb +20 -0
  123. metadata +110 -55
  124. data/app/helpers/spree/base_helper.rb +0 -45
  125. data/app/helpers/spree/digital_asset_helper.rb +0 -16
  126. data/app/helpers/spree/fulfillment_helper.rb +0 -12
  127. data/app/helpers/spree/mail_helper.rb +0 -10
  128. data/app/views/spree/company_mailer/invitation_email.html.erb +0 -8
  129. data/app/views/spree/company_mailer/invitation_email.text.erb +0 -11
  130. data/app/views/spree/customer_mailer/data_export_email.html.erb +0 -12
  131. data/app/views/spree/customer_mailer/data_export_email.text.erb +0 -9
  132. data/app/views/spree/customer_mailer/password_reset_email.html.erb +0 -10
  133. data/app/views/spree/customer_mailer/password_reset_email.text.erb +0 -13
  134. data/app/views/spree/digital_asset_mailer/files_ready_email.html.erb +0 -20
  135. data/app/views/spree/digital_asset_mailer/files_ready_email.text.erb +0 -10
  136. data/app/views/spree/fulfillment_mailer/fulfilled_email.html.erb +0 -22
  137. data/app/views/spree/fulfillment_mailer/fulfilled_email.text.erb +0 -18
  138. data/app/views/spree/newsletter_mailer/email_confirmation.html.erb +0 -12
  139. data/app/views/spree/newsletter_mailer/email_confirmation.text.erb +0 -9
  140. data/app/views/spree/order_group_mailer/confirm_email.html.erb +0 -38
  141. data/app/views/spree/order_group_mailer/confirm_email.text.erb +0 -26
  142. data/app/views/spree/order_group_mailer/store_owner_notification_email.html.erb +0 -14
  143. data/app/views/spree/order_group_mailer/store_owner_notification_email.text.erb +0 -11
  144. data/app/views/spree/order_mailer/cancel_email.html.erb +0 -12
  145. data/app/views/spree/order_mailer/cancel_email.text.erb +0 -13
  146. data/app/views/spree/order_mailer/confirm_email.html.erb +0 -12
  147. data/app/views/spree/order_mailer/confirm_email.text.erb +0 -13
  148. data/app/views/spree/order_mailer/payment_link_email.html.erb +0 -11
  149. data/app/views/spree/order_mailer/store_owner_notification_email.html.erb +0 -11
  150. data/app/views/spree/order_mailer/store_owner_notification_email.text.erb +0 -13
  151. data/app/views/spree/return_mailer/refunded_email.html.erb +0 -22
  152. data/app/views/spree/return_mailer/refunded_email.text.erb +0 -20
  153. data/app/views/spree/seller_mailer/approved_email.html.erb +0 -8
  154. data/app/views/spree/seller_mailer/approved_email.text.erb +0 -8
  155. data/app/views/spree/seller_mailer/rejected_email.html.erb +0 -6
  156. data/app/views/spree/seller_mailer/rejected_email.text.erb +0 -7
  157. data/app/views/spree/seller_mailer/suspended_email.html.erb +0 -6
  158. data/app/views/spree/seller_mailer/suspended_email.text.erb +0 -7
  159. data/app/views/spree/shared/_fulfillment_group_section.html.erb +0 -37
  160. data/app/views/spree/shared/_fulfillment_group_section.text.erb +0 -12
  161. data/app/views/spree/shared/_item_thumbnail_link.html.erb +0 -18
  162. data/app/views/spree/shared/_order_summary_section.html.erb +0 -20
  163. data/app/views/spree/shared/_po_number.text.erb +0 -6
  164. data/app/views/spree/shared/_purchase_totals.html.erb +0 -62
  165. data/app/views/spree/shared/_purchase_totals.text.erb +0 -24
  166. data/app/views/spree/shared/_purchased_items_table.html.erb +0 -41
  167. data/app/views/spree/shared/_purchased_items_table.text.erb +0 -28
  168. data/app/views/spree/shared/purchased_items_table/_line_item.html.erb +0 -24
  169. data/app/views/spree/shared/purchased_items_table/_subtotal.html.erb +0 -3
  170. data/app/views/spree/shared/purchased_items_table/_summary_row.html.erb +0 -14
  171. data/app/views/spree/shared/purchased_items_table/_total.html.erb +0 -4
  172. data/config/i18n-tasks.yml +0 -22
@@ -1,62 +0,0 @@
1
- <%# Every figure of the whole purchase, once. Locals: order_group.
2
-
3
- Deliberately not the order summary's own totals block: that one reaches
4
- into one order's fulfillments and money rows, and a purchase has neither
5
- of its own. These read the group's roll-up of what each child independently
6
- computed. Delivery is one line here and broken down per parcel above. %>
7
- <table class="section" width="100%" cellpadding="0" cellspacing="0" role="presentation">
8
- <tr>
9
- <td>
10
- <h3 class="f-fallback"><%= Spree.t(:order_summary) %></h3>
11
- <table class="summary purchase_content" width="100%" cellpadding="0" cellspacing="0" role="presentation">
12
- <%= render 'spree/shared/purchased_items_table/summary_row',
13
- label: Spree.t('order_mailer.subtotal'),
14
- value: order_group.display_item_total %>
15
-
16
- <% order_group.discounts.promotion.to_a.group_by(&:label).each do |label, discounts| %>
17
- <%= render 'spree/shared/purchased_items_table/summary_row',
18
- label: Spree.t(:promotion),
19
- sub: label,
20
- value: Spree::Money.new(discounts.sum(&:amount), currency: order_group.currency) %>
21
- <% end %>
22
-
23
- <% if order_group.delivery_total != 0 %>
24
- <%= render 'spree/shared/purchased_items_table/summary_row',
25
- label: Spree.t(:shipping),
26
- value: order_group.display_delivery_total %>
27
- <% end %>
28
-
29
- <% if order_group.additional_tax_total != 0 %>
30
- <%= render 'spree/shared/purchased_items_table/summary_row',
31
- label: Spree.t(:tax),
32
- value: order_group.display_additional_tax_total %>
33
- <% end %>
34
-
35
- <% if order_group.gift_card_total.positive? %>
36
- <%= render 'spree/shared/purchased_items_table/summary_row',
37
- label: Spree.t(:gift_card),
38
- value: safe_join(['-', order_group.display_gift_card_total.to_html]) %>
39
- <% end %>
40
-
41
- <% order_group.discounts.manual.to_a.group_by(&:label).each do |label, discounts| %>
42
- <%= render 'spree/shared/purchased_items_table/summary_row',
43
- label: label,
44
- value: Spree::Money.new(discounts.sum(&:amount), currency: order_group.currency) %>
45
- <% end %>
46
-
47
- <% order_group.fees.to_a.group_by(&:label).each do |label, fees| %>
48
- <% amount = fees.sum(&:amount) %>
49
- <% next if amount.zero? %>
50
- <%= render 'spree/shared/purchased_items_table/summary_row',
51
- label: label,
52
- value: Spree::Money.new(amount, currency: order_group.currency) %>
53
- <% end %>
54
-
55
- <%= render 'spree/shared/purchased_items_table/summary_row',
56
- row_class: 'summary_total',
57
- label: Spree.t('order_mailer.total'),
58
- value: order_group.display_total_minus_store_credits %>
59
- </table>
60
- </td>
61
- </tr>
62
- </table>
@@ -1,24 +0,0 @@
1
- ============================================================
2
- <%= Spree.t('order_mailer.subtotal') %> <%= order_group.display_item_total %>
3
- <% order_group.discounts.promotion.to_a.group_by(&:label).each do |label, discounts| %>
4
- <%= Spree.t(:promotion) %>: <%= label %> <%= Spree::Money.new(discounts.sum(&:amount), currency: order_group.currency) %>
5
- <% end %>
6
- <% if order_group.delivery_total != 0 %>
7
- <%= Spree.t(:shipping) %>: <%= order_group.display_delivery_total %>
8
- <% end %>
9
- <% if order_group.additional_tax_total != 0 %>
10
- <%= Spree.t(:tax) %>: <%= order_group.display_additional_tax_total %>
11
- <% end %>
12
- <% if order_group.gift_card_total.positive? %>
13
- <%= Spree.t(:gift_card) %>: -<%= order_group.display_gift_card_total %>
14
- <% end %>
15
- <% order_group.discounts.manual.to_a.group_by(&:label).each do |label, discounts| %>
16
- <%= label %> <%= Spree::Money.new(discounts.sum(&:amount), currency: order_group.currency) %>
17
- <% end %>
18
- <% order_group.fees.to_a.group_by(&:label).each do |label, fees| %>
19
- <% amount = fees.sum(&:amount) %>
20
- <% next if amount.zero? %>
21
- <%= label %> <%= Spree::Money.new(amount, currency: order_group.currency) %>
22
- <% end %>
23
- ============================================================
24
- <%= Spree.t('order_mailer.total') %> <%= order_group.display_total_minus_store_credits %>
@@ -1,41 +0,0 @@
1
- <%= render collection: line_items, partial: 'spree/shared/purchased_items_table/line_item', as: :line_item %>
2
-
3
- <% if local_assigns.fetch(:totals, true) %>
4
- <table class="summary purchase_content" width="100%" cellpadding="0" cellspacing="0" role="presentation">
5
- <%= render 'spree/shared/purchased_items_table/subtotal', order: order %>
6
- <% order.discounts.promotion.to_a.group_by(&:label).each do |label, discounts| %>
7
- <%= render 'spree/shared/purchased_items_table/summary_row',
8
- label: Spree.t(:promotion),
9
- sub: label,
10
- value: Spree::Money.new(discounts.sum(&:amount), currency: order.currency) %>
11
- <% end %>
12
- <% order.fulfillments.group_by { |f| f.selected_delivery_rate&.name }.each do |name, shipments| %>
13
- <%= render 'spree/shared/purchased_items_table/summary_row',
14
- label: Spree.t(:shipping),
15
- sub: name,
16
- value: Spree::Money.new(shipments.sum(&:cost), currency: order.currency) %>
17
- <% end %>
18
- <% if order.additional_tax_total != 0 %>
19
- <%= render 'spree/shared/purchased_items_table/summary_row',
20
- label: Spree.t(:tax),
21
- value: order.display_additional_tax_total %>
22
- <% end %>
23
- <% if order.gift_card_total.positive? %>
24
- <%= render 'spree/shared/purchased_items_table/summary_row',
25
- label: Spree.t(:gift_card),
26
- value: safe_join(['-', order.display_gift_card_total.to_html]) %>
27
- <% end %>
28
- <% order.discounts.manual.to_a.group_by(&:label).each do |label, discounts| %>
29
- <%= render 'spree/shared/purchased_items_table/summary_row',
30
- label: label,
31
- value: Spree::Money.new(discounts.sum(&:amount), currency: order.currency) %>
32
- <% end %>
33
- <% order.fees.each do |fee| %>
34
- <% next if fee.amount == 0 %>
35
- <%= render 'spree/shared/purchased_items_table/summary_row',
36
- label: fee.label,
37
- value: Spree::Money.new(fee.amount, currency: order.currency) %>
38
- <% end %>
39
- <%= render 'spree/shared/purchased_items_table/total', order: order %>
40
- </table>
41
- <% end %>
@@ -1,28 +0,0 @@
1
- <% line_items.each do |item| %>
2
- <%= item.variant.sku %> <%= item.variant.product.name %> <%= item.variant.options_text -%> (<%=item.quantity%>) <%= Spree.t('at_symbol') %> <%= item.single_money %> = <%= item.display_amount %>
3
- <% end %>
4
- ============================================================
5
- <%= Spree.t('order_mailer.subtotal') %> <%= order.display_item_total %>
6
- <% order.discounts.promotion.to_a.group_by(&:label).each do |label, discounts| %>
7
- <%= Spree.t(:promotion) %>: <%= label %> <%= Spree::Money.new(discounts.sum(&:amount), currency: order.currency) %>
8
- <% end %>
9
-
10
- <% order.fulfillments.group_by { |f| f.selected_delivery_rate.try(:name) }.each do |name, shipments| %>
11
- <%= Spree.t(:shipping) %>: <%= name %> <%= Spree::Money.new(shipments.sum(&:cost), currency: order.currency) %>
12
- <% end %>
13
-
14
- <% if order.additional_tax_total != 0 %>
15
- <%= Spree.t(:tax) %>: <%= order.display_additional_tax_total.to_html %>
16
- <% end %>
17
-
18
- <% if order.gift_card_total.positive? %>
19
- <%= Spree.t(:gift_card) %>: -<%= order.display_gift_card_total.to_html %>
20
- <% end %>
21
-
22
- <% order.discounts.manual.to_a.group_by(&:label).each do |label, discounts| %>
23
- <%= label %> <%= Spree::Money.new(discounts.sum(&:amount), currency: order.currency) %>
24
- <% end %>
25
- <% order.fees.each do |fee| %>
26
- <% next if fee.amount == 0 %>
27
- <%= fee.label %> <%= fee.display_amount %>
28
- <% end %>
@@ -1,24 +0,0 @@
1
- <%# One purchased line. Locals: line_item, and optionally quantity + amount
2
- for a view showing part of a line — a parcel carrying two of the three
3
- ordered, say — where the line's own figures describe more than is there. %>
4
- <% quantity = local_assigns.fetch(:quantity, line_item.quantity) %>
5
- <% amount = local_assigns.fetch(:amount, line_item.display_amount) %>
6
- <table class="item" width="100%" cellpadding="0" cellspacing="0" role="presentation">
7
- <tr>
8
- <td class="item_image" width="96" valign="middle">
9
- <% image = line_item.variant.primary_media || line_item.product.primary_media %>
10
- <% product_url = spree_storefront_resource_url(line_item.product) %>
11
- <%= render 'spree/shared/item_thumbnail_link', image: image, product_url: product_url, alt: line_item.name %>
12
- </td>
13
- <td class="item_info" valign="middle">
14
- <%= link_to line_item.name, product_url, class: 'f-fallback item_name' %>
15
- <% if line_item.variant.options_text.present? %>
16
- <p class="item_meta"><%= line_item.variant.options_text %></p>
17
- <% end %>
18
- </td>
19
- <td class="item_amount" align="right" valign="middle">
20
- <p class="item_qty f-fallback"><%= quantity %> x <%= line_item.single_money %></p>
21
- <p class="item_price f-fallback"><%= amount %></p>
22
- </td>
23
- </tr>
24
- </table>
@@ -1,3 +0,0 @@
1
- <%= render 'spree/shared/purchased_items_table/summary_row',
2
- label: Spree.t('order_mailer.subtotal'),
3
- value: order.display_item_total %>
@@ -1,14 +0,0 @@
1
- <%# One label/value row of the order summary. Locals: label, value,
2
- optional sub (secondary line under the label, e.g. the shipping rate name),
3
- optional row_class ('summary_total' for the emphasized final row). %>
4
- <tr class="<%= local_assigns[:row_class] %>">
5
- <td valign="top">
6
- <span class="f-fallback"><%= label %></span>
7
- <% if local_assigns[:sub].present? %>
8
- <span class="f-fallback summary_sub"><%= sub %></span>
9
- <% end %>
10
- </td>
11
- <td class="summary_value" align="right" valign="top">
12
- <span class="f-fallback"><%= value.respond_to?(:to_html) ? value.to_html : value %></span>
13
- </td>
14
- </tr>
@@ -1,4 +0,0 @@
1
- <%= render 'spree/shared/purchased_items_table/summary_row',
2
- row_class: 'summary_total',
3
- label: Spree.t('order_mailer.total'),
4
- value: order.display_total_minus_store_credits %>
@@ -1,22 +0,0 @@
1
- base_locale: en
2
-
3
- data:
4
- yaml:
5
- write:
6
- # do not wrap lines at 80 characters
7
- line_width: -1
8
-
9
- # Core's keys are read but never written here: the mailers and their
10
- # templates share the vocabulary every Spree surface uses (shipping, tax,
11
- # promotion) and only own the copy of the emails themselves.
12
- external:
13
- - "<%= File.expand_path('../core/config/locales', Dir.pwd) %>/%{locale}.yml"
14
-
15
- # Find translate calls
16
- search:
17
- paths:
18
- - 'app'
19
- - 'lib'
20
-
21
- # The PatternMapper for Spree.t
22
- <% I18n::Tasks.add_scanner 'I18n::Tasks::Scanners::PatternMapper', patterns: [['\bSpree\.t[( ]\s*%{key}', 'spree.%{key}']] %>