actiontext 7.0.8.1 → 7.2.2.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 (45) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +43 -124
  3. data/MIT-LICENSE +1 -1
  4. data/README.md +2 -2
  5. data/app/assets/javascripts/actiontext.esm.js +889 -0
  6. data/app/assets/javascripts/actiontext.js +55 -73
  7. data/app/assets/javascripts/trix.js +13612 -5170
  8. data/app/assets/stylesheets/trix.css +67 -30
  9. data/app/helpers/action_text/content_helper.rb +28 -4
  10. data/app/helpers/action_text/tag_helper.rb +44 -30
  11. data/app/models/action_text/encrypted_rich_text.rb +4 -2
  12. data/app/models/action_text/record.rb +2 -0
  13. data/app/models/action_text/rich_text.rb +66 -6
  14. data/app/views/action_text/attachables/_content_attachment.html.erb +3 -0
  15. data/db/migrate/20180528164100_create_action_text_tables.rb +1 -1
  16. data/lib/action_text/attachable.rb +71 -5
  17. data/lib/action_text/attachables/content_attachment.rb +22 -18
  18. data/lib/action_text/attachables/missing_attachable.rb +19 -3
  19. data/lib/action_text/attachables/remote_image.rb +2 -0
  20. data/lib/action_text/attachment.rb +45 -2
  21. data/lib/action_text/attachment_gallery.rb +2 -0
  22. data/lib/action_text/attachments/caching.rb +2 -0
  23. data/lib/action_text/attachments/minification.rb +2 -0
  24. data/lib/action_text/attachments/trix_conversion.rb +2 -0
  25. data/lib/action_text/attribute.rb +40 -21
  26. data/lib/action_text/content.rb +68 -3
  27. data/lib/action_text/deprecator.rb +9 -0
  28. data/lib/action_text/encryption.rb +2 -0
  29. data/lib/action_text/engine.rb +17 -9
  30. data/lib/action_text/fixture_set.rb +35 -33
  31. data/lib/action_text/fragment.rb +8 -3
  32. data/lib/action_text/gem_version.rb +5 -3
  33. data/lib/action_text/html_conversion.rb +3 -1
  34. data/lib/action_text/plain_text_conversion.rb +8 -1
  35. data/lib/action_text/rendering.rb +7 -2
  36. data/lib/action_text/serialization.rb +2 -0
  37. data/lib/action_text/system_test_helper.rb +20 -17
  38. data/lib/action_text/trix_attachment.rb +4 -2
  39. data/lib/action_text/version.rb +3 -1
  40. data/lib/action_text.rb +19 -0
  41. data/lib/generators/action_text/install/install_generator.rb +29 -5
  42. data/lib/generators/action_text/install/templates/actiontext.css +0 -4
  43. data/lib/rails/generators/test_unit/install_generator.rb +2 -0
  44. data/package.json +7 -7
  45. metadata +21 -18
@@ -1,8 +1,3 @@
1
- @charset "UTF-8";
2
- /*
3
- Trix 1.3.1
4
- Copyright © 2020 Basecamp, LLC
5
- http://trix-editor.org/*/
6
1
  trix-editor {
7
2
  border: 1px solid #bbb;
8
3
  border-radius: 3px;
@@ -10,13 +5,16 @@ trix-editor {
10
5
  padding: 0.4em 0.6em;
11
6
  min-height: 5em;
12
7
  outline: none; }
8
+
13
9
  trix-toolbar * {
14
10
  box-sizing: border-box; }
11
+
15
12
  trix-toolbar .trix-button-row {
16
13
  display: flex;
17
14
  flex-wrap: nowrap;
18
15
  justify-content: space-between;
19
16
  overflow-x: auto; }
17
+
20
18
  trix-toolbar .trix-button-group {
21
19
  display: flex;
22
20
  margin-bottom: 10px;
@@ -26,14 +24,16 @@ trix-toolbar .trix-button-group {
26
24
  border-radius: 3px; }
27
25
  trix-toolbar .trix-button-group:not(:first-child) {
28
26
  margin-left: 1.5vw; }
29
- @media (max-device-width: 768px) {
27
+ @media (max-width: 768px) {
30
28
  trix-toolbar .trix-button-group:not(:first-child) {
31
29
  margin-left: 0; } }
30
+
32
31
  trix-toolbar .trix-button-group-spacer {
33
32
  flex-grow: 1; }
34
- @media (max-device-width: 768px) {
33
+ @media (max-width: 768px) {
35
34
  trix-toolbar .trix-button-group-spacer {
36
35
  display: none; } }
36
+
37
37
  trix-toolbar .trix-button {
38
38
  position: relative;
39
39
  float: left;
@@ -57,17 +57,18 @@ trix-toolbar .trix-button {
57
57
  cursor: pointer; }
58
58
  trix-toolbar .trix-button:disabled {
59
59
  color: rgba(0, 0, 0, 0.125); }
60
- @media (max-device-width: 768px) {
60
+ @media (max-width: 768px) {
61
61
  trix-toolbar .trix-button {
62
62
  letter-spacing: -0.01em;
63
63
  padding: 0 0.3em; } }
64
+
64
65
  trix-toolbar .trix-button--icon {
65
66
  font-size: inherit;
66
67
  width: 2.6em;
67
68
  height: 1.6em;
68
69
  max-width: calc(0.8em + 4vw);
69
70
  text-indent: -9999px; }
70
- @media (max-device-width: 768px) {
71
+ @media (max-width: 768px) {
71
72
  trix-toolbar .trix-button--icon {
72
73
  height: 2em;
73
74
  max-width: calc(0.8em + 3.5vw); } }
@@ -83,7 +84,7 @@ trix-toolbar .trix-button--icon {
83
84
  background-position: center;
84
85
  background-repeat: no-repeat;
85
86
  background-size: contain; }
86
- @media (max-device-width: 768px) {
87
+ @media (max-width: 768px) {
87
88
  trix-toolbar .trix-button--icon::before {
88
89
  right: 6%;
89
90
  left: 6%; } }
@@ -91,38 +92,54 @@ trix-toolbar .trix-button--icon {
91
92
  opacity: 1; }
92
93
  trix-toolbar .trix-button--icon:disabled::before {
93
94
  opacity: 0.125; }
95
+
94
96
  trix-toolbar .trix-button--icon-attach::before {
95
- background-image: url(data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%3E%3Cpath%20d%3D%22M16.5%206v11.5a4%204%200%201%201-8%200V5a2.5%202.5%200%200%201%205%200v10.5a1%201%200%201%201-2%200V6H10v9.5a2.5%202.5%200%200%200%205%200V5a4%204%200%201%200-8%200v12.5a5.5%205.5%200%200%200%2011%200V6h-1.5z%22%2F%3E%3C%2Fsvg%3E);
97
+ background-image: url("data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20d%3D%22M10.5%2018V7.5c0-2.25%203-2.25%203%200V18c0%204.125-6%204.125-6%200V7.5c0-6.375%209-6.375%209%200V18%22%20stroke%3D%22%23000%22%20stroke-width%3D%222%22%20stroke-miterlimit%3D%2210%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%2F%3E%3C%2Fsvg%3E");
96
98
  top: 8%;
97
99
  bottom: 4%; }
100
+
98
101
  trix-toolbar .trix-button--icon-bold::before {
99
- background-image: url(data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%3E%3Cpath%20d%3D%22M15.6%2011.8c1-.7%201.6-1.8%201.6-2.8a4%204%200%200%200-4-4H7v14h7c2.1%200%203.7-1.7%203.7-3.8%200-1.5-.8-2.8-2.1-3.4zM10%207.5h3a1.5%201.5%200%201%201%200%203h-3v-3zm3.5%209H10v-3h3.5a1.5%201.5%200%201%201%200%203z%22%2F%3E%3C%2Fsvg%3E); }
102
+ background-image: url("data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20fill-rule%3D%22evenodd%22%20clip-rule%3D%22evenodd%22%20d%3D%22M6.522%2019.242a.5.5%200%200%201-.5-.5V5.35a.5.5%200%200%201%20.5-.5h5.783c1.347%200%202.46.345%203.24.982.783.64%201.216%201.562%201.216%202.683%200%201.13-.587%202.129-1.476%202.71a.35.35%200%200%200%20.049.613c1.259.56%202.101%201.742%202.101%203.22%200%201.282-.483%202.334-1.363%203.063-.876.726-2.132%201.12-3.66%201.12h-5.89ZM9.27%207.347v3.362h1.97c.766%200%201.347-.17%201.733-.464.38-.291.587-.716.587-1.27%200-.53-.183-.928-.513-1.198-.334-.273-.838-.43-1.505-.43H9.27Zm0%205.606v3.791h2.389c.832%200%201.448-.177%201.853-.497.399-.315.614-.786.614-1.423%200-.62-.22-1.077-.63-1.385-.418-.313-1.053-.486-1.905-.486H9.27Z%22%20fill%3D%22%23000%22%2F%3E%3C%2Fsvg%3E"); }
103
+
100
104
  trix-toolbar .trix-button--icon-italic::before {
101
- background-image: url(data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%3E%3Cpath%20d%3D%22M10%205v3h2.2l-3.4%208H6v3h8v-3h-2.2l3.4-8H18V5h-8z%22%2F%3E%3C%2Fsvg%3E); }
105
+ background-image: url("data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20fill-rule%3D%22evenodd%22%20clip-rule%3D%22evenodd%22%20d%3D%22M9%205h6.5v2h-2.23l-2.31%2010H13v2H6v-2h2.461l2.306-10H9V5Z%22%20fill%3D%22%23000%22%2F%3E%3C%2Fsvg%3E"); }
106
+
102
107
  trix-toolbar .trix-button--icon-link::before {
103
- background-image: url(data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%3E%3Cpath%20d%3D%22M9.88%2013.7a4.3%204.3%200%200%201%200-6.07l3.37-3.37a4.26%204.26%200%200%201%206.07%200%204.3%204.3%200%200%201%200%206.06l-1.96%201.72a.91.91%200%201%201-1.3-1.3l1.97-1.71a2.46%202.46%200%200%200-3.48-3.48l-3.38%203.37a2.46%202.46%200%200%200%200%203.48.91.91%200%201%201-1.3%201.3z%22%2F%3E%3Cpath%20d%3D%22M4.25%2019.46a4.3%204.3%200%200%201%200-6.07l1.93-1.9a.91.91%200%201%201%201.3%201.3l-1.93%201.9a2.46%202.46%200%200%200%203.48%203.48l3.37-3.38c.96-.96.96-2.52%200-3.48a.91.91%200%201%201%201.3-1.3%204.3%204.3%200%200%201%200%206.07l-3.38%203.38a4.26%204.26%200%200%201-6.07%200z%22%2F%3E%3C%2Fsvg%3E); }
108
+ background-image: url("data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20fill-rule%3D%22evenodd%22%20clip-rule%3D%22evenodd%22%20d%3D%22M18.948%205.258a4.337%204.337%200%200%200-6.108%200L11.217%206.87a.993.993%200%200%200%200%201.41c.392.39%201.027.39%201.418%200l1.623-1.613a2.323%202.323%200%200%201%203.271%200%202.29%202.29%200%200%201%200%203.251l-2.393%202.38a3.021%203.021%200%200%201-4.255%200l-.05-.049a1.007%201.007%200%200%200-1.418%200%20.993.993%200%200%200%200%201.41l.05.049a5.036%205.036%200%200%200%207.091%200l2.394-2.38a4.275%204.275%200%200%200%200-6.072Zm-13.683%2013.6a4.337%204.337%200%200%200%206.108%200l1.262-1.255a.993.993%200%200%200%200-1.41%201.007%201.007%200%200%200-1.418%200L9.954%2017.45a2.323%202.323%200%200%201-3.27%200%202.29%202.29%200%200%201%200-3.251l2.344-2.331a2.579%202.579%200%200%201%203.631%200c.392.39%201.027.39%201.419%200a.993.993%200%200%200%200-1.41%204.593%204.593%200%200%200-6.468%200l-2.345%202.33a4.275%204.275%200%200%200%200%206.072Z%22%20fill%3D%22%23000%22%2F%3E%3C%2Fsvg%3E"); }
109
+
104
110
  trix-toolbar .trix-button--icon-strike::before {
105
- background-image: url(data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%3E%3Cpath%20d%3D%22M12.73%2014l.28.14c.26.15.45.3.57.44.12.14.18.3.18.5%200%20.3-.15.56-.44.75-.3.2-.76.3-1.39.3A13.52%2013.52%200%200%201%207%2014.95v3.37a10.64%2010.64%200%200%200%204.84.88c1.26%200%202.35-.19%203.28-.56.93-.37%201.64-.9%202.14-1.57s.74-1.45.74-2.32c0-.26-.02-.51-.06-.75h-5.21zm-5.5-4c-.08-.34-.12-.7-.12-1.1%200-1.29.52-2.3%201.58-3.02%201.05-.72%202.5-1.08%204.34-1.08%201.62%200%203.28.34%204.97%201l-1.3%202.93c-1.47-.6-2.73-.9-3.8-.9-.55%200-.96.08-1.2.26-.26.17-.38.38-.38.64%200%20.27.16.52.48.74.17.12.53.3%201.05.53H7.23zM3%2013h18v-2H3v2z%22%2F%3E%3C%2Fsvg%3E); }
111
+ background-image: url("data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20fill-rule%3D%22evenodd%22%20clip-rule%3D%22evenodd%22%20d%3D%22M6%2014.986c.088%202.647%202.246%204.258%205.635%204.258%203.496%200%205.713-1.728%205.713-4.463%200-.275-.02-.536-.062-.781h-3.461c.398.293.573.654.573%201.123%200%201.035-1.074%201.787-2.646%201.787-1.563%200-2.773-.762-2.91-1.924H6ZM6.432%2010h3.763c-.632-.314-.914-.715-.914-1.273%200-1.045.977-1.739%202.432-1.739%201.475%200%202.52.723%202.617%201.914h2.764c-.05-2.548-2.11-4.238-5.39-4.238-3.145%200-5.392%201.719-5.392%204.316%200%20.363.04.703.12%201.02ZM4%2011a1%201%200%201%200%200%202h15a1%201%200%201%200%200-2H4Z%22%20fill%3D%22%23000%22%2F%3E%3C%2Fsvg%3E"); }
112
+
106
113
  trix-toolbar .trix-button--icon-quote::before {
107
- background-image: url(data:image/svg+xml,%3Csvg%20version%3D%221%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%3E%3Cpath%20d%3D%22M6%2017h3l2-4V7H5v6h3zm8%200h3l2-4V7h-6v6h3z%22%2F%3E%3C%2Fsvg%3E); }
114
+ background-image: url("data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20d%3D%22M4.581%208.471c.44-.5%201.056-.834%201.758-.995C8.074%207.17%209.201%207.822%2010%208.752c1.354%201.578%201.33%203.555.394%205.277-.941%201.731-2.788%203.163-4.988%203.56a.622.622%200%200%201-.653-.317c-.113-.205-.121-.49.16-.764.294-.286.567-.566.791-.835.222-.266.413-.54.524-.815.113-.28.156-.597.026-.908-.128-.303-.39-.524-.72-.69a3.02%203.02%200%200%201-1.674-2.7c0-.905.283-1.59.72-2.088Zm9.419%200c.44-.5%201.055-.834%201.758-.995%201.734-.306%202.862.346%203.66%201.276%201.355%201.578%201.33%203.555.395%205.277-.941%201.731-2.789%203.163-4.988%203.56a.622.622%200%200%201-.653-.317c-.113-.205-.122-.49.16-.764.294-.286.567-.566.791-.835.222-.266.412-.54.523-.815.114-.28.157-.597.026-.908-.127-.303-.39-.524-.72-.69a3.02%203.02%200%200%201-1.672-2.701c0-.905.283-1.59.72-2.088Z%22%20fill%3D%22%23000%22%2F%3E%3C%2Fsvg%3E"); }
115
+
108
116
  trix-toolbar .trix-button--icon-heading-1::before {
109
- background-image: url(data:image/svg+xml,%3Csvg%20version%3D%221%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%3E%3Cpath%20d%3D%22M12%209v3H9v7H6v-7H3V9h9zM8%204h14v3h-6v12h-3V7H8V4z%22%2F%3E%3C%2Fsvg%3E); }
117
+ background-image: url("data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20fill-rule%3D%22evenodd%22%20clip-rule%3D%22evenodd%22%20d%3D%22M21.5%207.5v-3h-12v3H14v13h3v-13h4.5ZM9%2013.5h3.5v-3h-10v3H6v7h3v-7Z%22%20fill%3D%22%23000%22%2F%3E%3C%2Fsvg%3E"); }
118
+
110
119
  trix-toolbar .trix-button--icon-code::before {
111
- background-image: url(data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%3E%3Cpath%20d%3D%22M18.2%2012L15%2015.2l1.4%201.4L21%2012l-4.6-4.6L15%208.8l3.2%203.2zM5.8%2012L9%208.8%207.6%207.4%203%2012l4.6%204.6L9%2015.2%205.8%2012z%22%2F%3E%3C%2Fsvg%3E); }
120
+ background-image: url("data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20fill-rule%3D%22evenodd%22%20clip-rule%3D%22evenodd%22%20d%3D%22M3.293%2011.293a1%201%200%200%200%200%201.414l4%204a1%201%200%201%200%201.414-1.414L5.414%2012l3.293-3.293a1%201%200%200%200-1.414-1.414l-4%204Zm13.414%205.414%204-4a1%201%200%200%200%200-1.414l-4-4a1%201%200%201%200-1.414%201.414L18.586%2012l-3.293%203.293a1%201%200%200%200%201.414%201.414Z%22%20fill%3D%22%23000%22%2F%3E%3C%2Fsvg%3E"); }
121
+
112
122
  trix-toolbar .trix-button--icon-bullet-list::before {
113
- background-image: url(data:image/svg+xml,%3Csvg%20version%3D%221%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%3E%3Cpath%20d%3D%22M4%204a2%202%200%201%200%200%204%202%202%200%200%200%200-4zm0%206a2%202%200%201%200%200%204%202%202%200%200%200%200-4zm0%206a2%202%200%201%200%200%204%202%202%200%200%200%200-4zm4%203h14v-2H8v2zm0-6h14v-2H8v2zm0-8v2h14V5H8z%22%2F%3E%3C%2Fsvg%3E); }
123
+ background-image: url("data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20fill-rule%3D%22evenodd%22%20clip-rule%3D%22evenodd%22%20d%3D%22M5%207.5a1.5%201.5%200%201%200%200-3%201.5%201.5%200%200%200%200%203ZM8%206a1%201%200%200%201%201-1h11a1%201%200%201%201%200%202H9a1%201%200%200%201-1-1Zm1%205a1%201%200%201%200%200%202h11a1%201%200%201%200%200-2H9Zm0%206a1%201%200%201%200%200%202h11a1%201%200%201%200%200-2H9Zm-2.5-5a1.5%201.5%200%201%201-3%200%201.5%201.5%200%200%201%203%200ZM5%2019.5a1.5%201.5%200%201%200%200-3%201.5%201.5%200%200%200%200%203Z%22%20fill%3D%22%23000%22%2F%3E%3C%2Fsvg%3E"); }
124
+
114
125
  trix-toolbar .trix-button--icon-number-list::before {
115
- background-image: url(data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%3E%3Cpath%20d%3D%22M2%2017h2v.5H3v1h1v.5H2v1h3v-4H2v1zm1-9h1V4H2v1h1v3zm-1%203h1.8L2%2013.1v.9h3v-1H3.2L5%2010.9V10H2v1zm5-6v2h14V5H7zm0%2014h14v-2H7v2zm0-6h14v-2H7v2z%22%2F%3E%3C%2Fsvg%3E); }
126
+ background-image: url("data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20fill-rule%3D%22evenodd%22%20clip-rule%3D%22evenodd%22%20d%3D%22M3%204h2v4H4V5H3V4Zm5%202a1%201%200%200%201%201-1h11a1%201%200%201%201%200%202H9a1%201%200%200%201-1-1Zm1%205a1%201%200%201%200%200%202h11a1%201%200%201%200%200-2H9Zm0%206a1%201%200%201%200%200%202h11a1%201%200%201%200%200-2H9Zm-3.5-7H6v1l-1.5%202H6v1H3v-1l1.667-2H3v-1h2.5ZM3%2017v-1h3v4H3v-1h2v-.5H4v-1h1V17H3Z%22%20fill%3D%22%23000%22%2F%3E%3C%2Fsvg%3E"); }
127
+
116
128
  trix-toolbar .trix-button--icon-undo::before {
117
- background-image: url(data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%3E%3Cpath%20d%3D%22M12.5%208c-2.6%200-5%201-6.9%202.6L2%207v9h9l-3.6-3.6A8%208%200%200%201%2020%2016l2.4-.8a10.5%2010.5%200%200%200-10-7.2z%22%2F%3E%3C%2Fsvg%3E); }
129
+ background-image: url("data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20fill-rule%3D%22evenodd%22%20clip-rule%3D%22evenodd%22%20d%3D%22M3%2014a1%201%200%200%200%201%201h6a1%201%200%201%200%200-2H6.257c2.247-2.764%205.151-3.668%207.579-3.264%202.589.432%204.739%202.356%205.174%205.405a1%201%200%200%200%201.98-.283c-.564-3.95-3.415-6.526-6.825-7.095C11.084%207.25%207.63%208.377%205%2011.39V8a1%201%200%200%200-2%200v6Zm2-1Z%22%20fill%3D%22%23000%22%2F%3E%3C%2Fsvg%3E"); }
130
+
118
131
  trix-toolbar .trix-button--icon-redo::before {
119
- background-image: url(data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%3E%3Cpath%20d%3D%22M18.4%2010.6a10.5%2010.5%200%200%200-16.9%204.6L4%2016a8%208%200%200%201%2012.7-3.6L13%2016h9V7l-3.6%203.6z%22%2F%3E%3C%2Fsvg%3E); }
132
+ background-image: url("data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20fill-rule%3D%22evenodd%22%20clip-rule%3D%22evenodd%22%20d%3D%22M21%2014a1%201%200%200%201-1%201h-6a1%201%200%201%201%200-2h3.743c-2.247-2.764-5.151-3.668-7.579-3.264-2.589.432-4.739%202.356-5.174%205.405a1%201%200%200%201-1.98-.283c.564-3.95%203.415-6.526%206.826-7.095%203.08-.513%206.534.614%209.164%203.626V8a1%201%200%201%201%202%200v6Zm-2-1Z%22%20fill%3D%22%23000%22%2F%3E%3C%2Fsvg%3E"); }
133
+
120
134
  trix-toolbar .trix-button--icon-decrease-nesting-level::before {
121
- background-image: url(data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%3E%3Cpath%20d%3D%22M3%2019h19v-2H3v2zm7-6h12v-2H10v2zm-8.3-.3l2.8%202.9L6%2014.2%204%2012l2-2-1.4-1.5L1%2012l.7.7zM3%205v2h19V5H3z%22%2F%3E%3C%2Fsvg%3E); }
135
+ background-image: url("data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20fill-rule%3D%22evenodd%22%20clip-rule%3D%22evenodd%22%20d%3D%22M5%206a1%201%200%200%201%201-1h12a1%201%200%201%201%200%202H6a1%201%200%200%201-1-1Zm4%205a1%201%200%201%200%200%202h9a1%201%200%201%200%200-2H9Zm-3%206a1%201%200%201%200%200%202h12a1%201%200%201%200%200-2H6Zm-3.707-5.707a1%201%200%200%200%200%201.414l2%202a1%201%200%201%200%201.414-1.414L4.414%2012l1.293-1.293a1%201%200%200%200-1.414-1.414l-2%202Z%22%20fill%3D%22%23000%22%2F%3E%3C%2Fsvg%3E"); }
136
+
122
137
  trix-toolbar .trix-button--icon-increase-nesting-level::before {
123
- background-image: url(data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%3E%3Cpath%20d%3D%22M3%2019h19v-2H3v2zm7-6h12v-2H10v2zm-6.9-1L1%2014.2l1.4%201.4L6%2012l-.7-.7-2.8-2.8L1%209.9%203.1%2012zM3%205v2h19V5H3z%22%2F%3E%3C%2Fsvg%3E); }
138
+ background-image: url("data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20fill-rule%3D%22evenodd%22%20clip-rule%3D%22evenodd%22%20d%3D%22M5%206a1%201%200%200%201%201-1h12a1%201%200%201%201%200%202H6a1%201%200%200%201-1-1Zm4%205a1%201%200%201%200%200%202h9a1%201%200%201%200%200-2H9Zm-3%206a1%201%200%201%200%200%202h12a1%201%200%201%200%200-2H6Zm-2.293-2.293%202-2a1%201%200%200%200%200-1.414l-2-2a1%201%200%201%200-1.414%201.414L3.586%2012l-1.293%201.293a1%201%200%201%200%201.414%201.414Z%22%20fill%3D%22%23000%22%2F%3E%3C%2Fsvg%3E"); }
139
+
124
140
  trix-toolbar .trix-dialogs {
125
141
  position: relative; }
142
+
126
143
  trix-toolbar .trix-dialog {
127
144
  position: absolute;
128
145
  top: 0;
@@ -135,6 +152,7 @@ trix-toolbar .trix-dialog {
135
152
  border-top: 2px solid #888;
136
153
  border-radius: 5px;
137
154
  z-index: 5; }
155
+
138
156
  trix-toolbar .trix-input--dialog {
139
157
  font-size: inherit;
140
158
  font-weight: normal;
@@ -149,12 +167,15 @@ trix-toolbar .trix-input--dialog {
149
167
  -moz-appearance: none; }
150
168
  trix-toolbar .trix-input--dialog.validate:invalid {
151
169
  box-shadow: #F00 0px 0px 1.5px 1px; }
170
+
152
171
  trix-toolbar .trix-button--dialog {
153
172
  font-size: inherit;
154
173
  padding: 0.5em;
155
174
  border-bottom: none; }
175
+
156
176
  trix-toolbar .trix-dialog--link {
157
177
  max-width: 600px; }
178
+
158
179
  trix-toolbar .trix-dialog__link-fields {
159
180
  display: flex;
160
181
  align-items: baseline; }
@@ -163,6 +184,7 @@ trix-toolbar .trix-dialog__link-fields {
163
184
  trix-toolbar .trix-dialog__link-fields .trix-button-group {
164
185
  flex: 0 0 content;
165
186
  margin: 0; }
187
+
166
188
  trix-editor [data-trix-mutable]:not(.attachment__caption-editor) {
167
189
  -webkit-user-select: none;
168
190
  -moz-user-select: none;
@@ -172,26 +194,32 @@ trix-editor [data-trix-mutable]:not(.attachment__caption-editor) {
172
194
  trix-editor [data-trix-mutable]::-moz-selection,
173
195
  trix-editor [data-trix-cursor-target]::-moz-selection, trix-editor [data-trix-mutable] ::-moz-selection {
174
196
  background: none; }
197
+
175
198
  trix-editor [data-trix-mutable]::selection,
176
199
  trix-editor [data-trix-cursor-target]::selection, trix-editor [data-trix-mutable] ::selection {
177
200
  background: none; }
178
201
 
179
- trix-editor [data-trix-mutable].attachment__caption-editor:focus::-moz-selection {
202
+ trix-editor .attachment__caption-editor:focus[data-trix-mutable]::-moz-selection {
180
203
  background: highlight; }
181
- trix-editor [data-trix-mutable].attachment__caption-editor:focus::selection {
204
+
205
+ trix-editor .attachment__caption-editor:focus[data-trix-mutable]::selection {
182
206
  background: highlight; }
183
207
 
184
208
  trix-editor [data-trix-mutable].attachment.attachment--file {
185
209
  box-shadow: 0 0 0 2px highlight;
186
210
  border-color: transparent; }
211
+
187
212
  trix-editor [data-trix-mutable].attachment img {
188
213
  box-shadow: 0 0 0 2px highlight; }
214
+
189
215
  trix-editor .attachment {
190
216
  position: relative; }
191
217
  trix-editor .attachment:hover {
192
218
  cursor: default; }
219
+
193
220
  trix-editor .attachment--preview .attachment__caption:hover {
194
221
  cursor: text; }
222
+
195
223
  trix-editor .attachment__progress {
196
224
  position: absolute;
197
225
  z-index: 1;
@@ -203,6 +231,7 @@ trix-editor .attachment__progress {
203
231
  transition: opacity 200ms ease-in; }
204
232
  trix-editor .attachment__progress[value="100"] {
205
233
  opacity: 0; }
234
+
206
235
  trix-editor .attachment__caption-editor {
207
236
  display: inline-block;
208
237
  width: 100%;
@@ -218,6 +247,7 @@ trix-editor .attachment__caption-editor {
218
247
  outline: none;
219
248
  -webkit-appearance: none;
220
249
  -moz-appearance: none; }
250
+
221
251
  trix-editor .attachment__toolbar {
222
252
  position: absolute;
223
253
  z-index: 1;
@@ -225,8 +255,10 @@ trix-editor .attachment__toolbar {
225
255
  left: 0;
226
256
  width: 100%;
227
257
  text-align: center; }
258
+
228
259
  trix-editor .trix-button-group {
229
260
  display: inline-flex; }
261
+
230
262
  trix-editor .trix-button {
231
263
  position: relative;
232
264
  float: left;
@@ -245,6 +277,7 @@ trix-editor .trix-button {
245
277
  background: #cbeefa; }
246
278
  trix-editor .trix-button:not(:disabled) {
247
279
  cursor: pointer; }
280
+
248
281
  trix-editor .trix-button--remove {
249
282
  text-indent: -9999px;
250
283
  display: inline-block;
@@ -266,7 +299,7 @@ trix-editor .trix-button--remove {
266
299
  left: 0;
267
300
  opacity: 0.7;
268
301
  content: "";
269
- background-image: url(data:image/svg+xml,%3Csvg%20height%3D%2224%22%20width%3D%2224%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20d%3D%22M19%206.4L17.6%205%2012%2010.6%206.4%205%205%206.4l5.6%205.6L5%2017.6%206.4%2019l5.6-5.6%205.6%205.6%201.4-1.4-5.6-5.6z%22%2F%3E%3Cpath%20d%3D%22M0%200h24v24H0z%22%20fill%3D%22none%22%2F%3E%3C%2Fsvg%3E);
302
+ background-image: url("data:image/svg+xml,%3Csvg%20height%3D%2224%22%20width%3D%2224%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20d%3D%22M19%206.41%2017.59%205%2012%2010.59%206.41%205%205%206.41%2010.59%2012%205%2017.59%206.41%2019%2012%2013.41%2017.59%2019%2019%2017.59%2013.41%2012z%22%2F%3E%3Cpath%20d%3D%22M0%200h24v24H0z%22%20fill%3D%22none%22%2F%3E%3C%2Fsvg%3E");
270
303
  background-position: center;
271
304
  background-repeat: no-repeat;
272
305
  background-size: 90%; }
@@ -274,8 +307,10 @@ trix-editor .trix-button--remove {
274
307
  border-color: #333; }
275
308
  trix-editor .trix-button--remove:hover::before {
276
309
  opacity: 1; }
310
+
277
311
  trix-editor .attachment__metadata-container {
278
312
  position: relative; }
313
+
279
314
  trix-editor .attachment__metadata {
280
315
  position: absolute;
281
316
  left: 50%;
@@ -297,9 +332,11 @@ trix-editor .attachment__metadata {
297
332
  trix-editor .attachment__metadata .attachment__size {
298
333
  margin-left: 0.2em;
299
334
  white-space: nowrap; }
300
- @charset "UTF-8";
335
+
301
336
  .trix-content {
302
- line-height: 1.5; }
337
+ line-height: 1.5;
338
+ overflow-wrap: break-word;
339
+ word-break: break-word; }
303
340
  .trix-content * {
304
341
  box-sizing: border-box;
305
342
  margin: 0;
@@ -347,7 +384,7 @@ trix-editor .attachment__metadata {
347
384
  .trix-content .attachment__caption {
348
385
  text-align: center; }
349
386
  .trix-content .attachment__caption .attachment__name + .attachment__size::before {
350
- content: ' · '; }
387
+ content: ' \2022 '; }
351
388
  .trix-content .attachment--preview {
352
389
  width: 100%;
353
390
  text-align: center; }
@@ -1,12 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  require "rails-html-sanitizer"
4
6
 
5
7
  module ActionText
6
8
  module ContentHelper
7
- mattr_accessor(:sanitizer) { Rails::Html::Sanitizer.safe_list_sanitizer.new }
8
- mattr_accessor(:allowed_tags) { sanitizer.class.allowed_tags + [ ActionText::Attachment.tag_name, "figure", "figcaption" ] }
9
- mattr_accessor(:allowed_attributes) { sanitizer.class.allowed_attributes + ActionText::Attachment::ATTRIBUTES }
9
+ mattr_accessor(:sanitizer, default: Rails::HTML4::Sanitizer.safe_list_sanitizer.new)
10
+ mattr_accessor(:allowed_tags)
11
+ mattr_accessor(:allowed_attributes)
10
12
  mattr_accessor(:scrubber)
11
13
 
12
14
  def render_action_text_content(content)
@@ -14,8 +16,22 @@ module ActionText
14
16
  sanitize_action_text_content(render_action_text_attachments(content))
15
17
  end
16
18
 
19
+ def sanitize_content_attachment(content_attachment)
20
+ sanitizer.sanitize(
21
+ content_attachment,
22
+ tags: sanitizer_allowed_tags,
23
+ attributes: sanitizer_allowed_attributes,
24
+ scrubber: scrubber,
25
+ )
26
+ end
27
+
17
28
  def sanitize_action_text_content(content)
18
- sanitizer.sanitize(content.to_html, tags: allowed_tags, attributes: allowed_attributes, scrubber: scrubber).html_safe
29
+ sanitizer.sanitize(
30
+ content.to_html,
31
+ tags: sanitizer_allowed_tags,
32
+ attributes: sanitizer_allowed_attributes,
33
+ scrubber: scrubber,
34
+ ).html_safe
19
35
  end
20
36
 
21
37
  def render_action_text_attachments(content)
@@ -48,5 +64,13 @@ module ActionText
48
64
 
49
65
  render(**options).chomp
50
66
  end
67
+
68
+ def sanitizer_allowed_tags
69
+ allowed_tags || (sanitizer.class.allowed_tags + [ ActionText::Attachment.tag_name, "figure", "figcaption" ])
70
+ end
71
+
72
+ def sanitizer_allowed_attributes
73
+ allowed_attributes || (sanitizer.class.allowed_attributes + ActionText::Attachment::ATTRIBUTES)
74
+ end
51
75
  end
52
76
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  require "active_support/core_ext/object/try"
4
6
  require "action_view/helpers/tags/placeholderable"
5
7
 
@@ -7,20 +9,24 @@ module ActionText
7
9
  module TagHelper
8
10
  cattr_accessor(:id, instance_accessor: false) { 0 }
9
11
 
10
- # Returns a +trix-editor+ tag that instantiates the Trix JavaScript editor as well as a hidden field
11
- # that Trix will write to on changes, so the content will be sent on form submissions.
12
+ # Returns a `trix-editor` tag that instantiates the Trix JavaScript editor as
13
+ # well as a hidden field that Trix will write to on changes, so the content will
14
+ # be sent on form submissions.
15
+ #
16
+ # #### Options
17
+ # * `:class` - Defaults to "trix-content" so that default styles will be
18
+ # applied. Setting this to a different value will prevent default styles
19
+ # from being applied.
20
+ # * `[:data][:direct_upload_url]` - Defaults to `rails_direct_uploads_url`.
21
+ # * `[:data][:blob_url_template]` - Defaults to
22
+ # `rails_service_blob_url(":signed_id", ":filename")`.
12
23
  #
13
- # ==== Options
14
- # * <tt>:class</tt> - Defaults to "trix-content" so that default styles will be applied.
15
- # Setting this to a different value will prevent default styles from being applied.
16
- # * <tt>[:data][:direct_upload_url]</tt> - Defaults to +rails_direct_uploads_url+.
17
- # * <tt>[:data][:blob_url_template]</tt> - Defaults to <tt>rails_service_blob_url(":signed_id", ":filename")</tt>.
18
24
  #
19
- # ==== Example
25
+ # #### Example
20
26
  #
21
- # rich_text_area_tag "content", message.content
22
- # # <input type="hidden" name="content" id="trix_input_post_1">
23
- # # <trix-editor id="content" input="trix_input_post_1" class="trix-content" ...></trix-editor>
27
+ # rich_text_area_tag "content", message.content
28
+ # # <input type="hidden" name="content" id="trix_input_post_1">
29
+ # # <trix-editor id="content" input="trix_input_post_1" class="trix-content" ...></trix-editor>
24
30
  def rich_text_area_tag(name, value = nil, options = {})
25
31
  options = options.symbolize_keys
26
32
  form = options.delete(:form)
@@ -50,38 +56,46 @@ module ActionView::Helpers
50
56
  options = @options.stringify_keys
51
57
  add_default_name_and_id(options)
52
58
  options["input"] ||= dom_id(object, [options["id"], :trix_input].compact.join("_")) if object
53
- @template_object.rich_text_area_tag(options.delete("name"), options.fetch("value") { value }, options.except("value"))
59
+ html_tag = @template_object.rich_text_area_tag(options.delete("name"), options.fetch("value") { value }, options.except("value"))
60
+ error_wrapping(html_tag)
54
61
  end
55
62
  end
56
63
 
57
64
  module FormHelper
58
- # Returns a +trix-editor+ tag that instantiates the Trix JavaScript editor as well as a hidden field
59
- # that Trix will write to on changes, so the content will be sent on form submissions.
65
+ # Returns a `trix-editor` tag that instantiates the Trix JavaScript editor as
66
+ # well as a hidden field that Trix will write to on changes, so the content will
67
+ # be sent on form submissions.
68
+ #
69
+ # #### Options
70
+ # * `:class` - Defaults to "trix-content" which ensures default styling is
71
+ # applied.
72
+ # * `:value` - Adds a default value to the HTML input tag.
73
+ # * `[:data][:direct_upload_url]` - Defaults to `rails_direct_uploads_url`.
74
+ # * `[:data][:blob_url_template]` - Defaults to
75
+ # `rails_service_blob_url(":signed_id", ":filename")`.
60
76
  #
61
- # ==== Options
62
- # * <tt>:class</tt> - Defaults to "trix-content" which ensures default styling is applied.
63
- # * <tt>:value</tt> - Adds a default value to the HTML input tag.
64
- # * <tt>[:data][:direct_upload_url]</tt> - Defaults to +rails_direct_uploads_url+.
65
- # * <tt>[:data][:blob_url_template]</tt> - Defaults to <tt>rails_service_blob_url(":signed_id", ":filename")</tt>.
66
77
  #
67
- # ==== Example
68
- # form_with(model: @message) do |form|
69
- # form.rich_text_area :content
70
- # end
71
- # # <input type="hidden" name="message[content]" id="message_content_trix_input_message_1">
72
- # # <trix-editor id="content" input="message_content_trix_input_message_1" class="trix-content" ...></trix-editor>
78
+ # #### Example
79
+ # rich_text_area :message, :content
80
+ # # <input type="hidden" name="message[content]" id="message_content_trix_input_message_1">
81
+ # # <trix-editor id="content" input="message_content_trix_input_message_1" class="trix-content" ...></trix-editor>
73
82
  #
74
- # form_with(model: @message) do |form|
75
- # form.rich_text_area :content, value: "<h1>Default message</h1>"
76
- # end
77
- # # <input type="hidden" name="message[content]" id="message_content_trix_input_message_1" value="<h1>Default message</h1>">
78
- # # <trix-editor id="content" input="message_content_trix_input_message_1" class="trix-content" ...></trix-editor>
83
+ # rich_text_area :message, :content, value: "<h1>Default message</h1>"
84
+ # # <input type="hidden" name="message[content]" id="message_content_trix_input_message_1" value="<h1>Default message</h1>">
85
+ # # <trix-editor id="content" input="message_content_trix_input_message_1" class="trix-content" ...></trix-editor>
79
86
  def rich_text_area(object_name, method, options = {})
80
87
  Tags::ActionText.new(object_name, method, self, options).render
81
88
  end
82
89
  end
83
90
 
84
91
  class FormBuilder
92
+ # Wraps ActionView::Helpers::FormHelper#rich_text_area for form builders:
93
+ #
94
+ # <%= form_with model: @message do |f| %>
95
+ # <%= f.rich_text_area :content %>
96
+ # <% end %>
97
+ #
98
+ # Please refer to the documentation of the base helper for details.
85
99
  def rich_text_area(method, options = {})
86
100
  @template.rich_text_area(@object_name, method, objectify_options(options))
87
101
  end
@@ -1,9 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  module ActionText
4
6
  class EncryptedRichText < RichText
5
- self.table_name = "action_text_rich_texts"
6
-
7
7
  encrypts :body
8
8
  end
9
9
  end
10
+
11
+ ActiveSupport.run_load_hooks :action_text_encrypted_rich_text, ActionText::EncryptedRichText
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  module ActionText
4
6
  class Record < ActiveRecord::Base # :nodoc:
5
7
  self.abstract_class = true
@@ -1,27 +1,87 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  module ActionText
4
- # The RichText record holds the content produced by the Trix editor in a serialized +body+ attribute.
5
- # It also holds all the references to the embedded files, which are stored using Active Storage.
6
- # This record is then associated with the Active Record model the application desires to have
7
- # rich text content using the +has_rich_text+ class method.
6
+ # # Action Text RichText
7
+ #
8
+ # The RichText record holds the content produced by the Trix editor in a
9
+ # serialized `body` attribute. It also holds all the references to the embedded
10
+ # files, which are stored using Active Storage. This record is then associated
11
+ # with the Active Record model the application desires to have rich text content
12
+ # using the `has_rich_text` class method.
13
+ #
14
+ # class Message < ActiveRecord::Base
15
+ # has_rich_text :content
16
+ # end
17
+ #
18
+ # message = Message.create!(content: "<h1>Funny times!</h1>")
19
+ # message.content #=> #<ActionText::RichText....
20
+ # message.content.to_s # => "<h1>Funny times!</h1>"
21
+ # message.content.to_plain_text # => "Funny times!"
22
+ #
23
+ # message = Message.create!(content: "<div onclick='action()'>safe<script>unsafe</script></div>")
24
+ # message.content #=> #<ActionText::RichText....
25
+ # message.content.to_s # => "<div>safeunsafe</div>"
26
+ # message.content.to_plain_text # => "safeunsafe"
8
27
  class RichText < Record
9
- self.table_name = "action_text_rich_texts"
28
+ ##
29
+ # :method: to_s
30
+ #
31
+ # Safely transforms RichText into an HTML String.
32
+ #
33
+ # message = Message.create!(content: "<h1>Funny times!</h1>")
34
+ # message.content.to_s # => "<h1>Funny times!</h1>"
35
+ #
36
+ # message = Message.create!(content: "<div onclick='action()'>safe<script>unsafe</script></div>")
37
+ # message.content.to_s # => "<div>safeunsafe</div>"
10
38
 
11
- serialize :body, ActionText::Content
39
+ serialize :body, coder: ActionText::Content
12
40
  delegate :to_s, :nil?, to: :body
13
41
 
42
+ ##
43
+ # :method: record
44
+ #
45
+ # Returns the associated record.
14
46
  belongs_to :record, polymorphic: true, touch: true
47
+
48
+ ##
49
+ # :method: embeds
50
+ #
51
+ # Returns the `ActiveStorage::Blob`s of the embedded files.
15
52
  has_many_attached :embeds
16
53
 
17
54
  before_save do
18
55
  self.embeds = body.attachables.grep(ActiveStorage::Blob).uniq if body.present?
19
56
  end
20
57
 
58
+ # Returns a plain-text version of the markup contained by the `body` attribute,
59
+ # with tags removed but HTML entities encoded.
60
+ #
61
+ # message = Message.create!(content: "<h1>Funny times!</h1>")
62
+ # message.content.to_plain_text # => "Funny times!"
63
+ #
64
+ # NOTE: that the returned string is not HTML safe and should not be rendered in
65
+ # browsers.
66
+ #
67
+ # message = Message.create!(content: "&lt;script&gt;alert()&lt;/script&gt;")
68
+ # message.content.to_plain_text # => "<script>alert()</script>"
21
69
  def to_plain_text
22
70
  body&.to_plain_text.to_s
23
71
  end
24
72
 
73
+ # Returns the `body` attribute in a format that makes it editable in the Trix
74
+ # editor. Previews of attachments are rendered inline.
75
+ #
76
+ # content = "<h1>Funny Times!</h1><figure data-trix-attachment='{\"sgid\":\"..."\}'></figure>"
77
+ # message = Message.create!(content: content)
78
+ # message.content.to_trix_html # =>
79
+ # # <div class="trix-content">
80
+ # # <h1>Funny times!</h1>
81
+ # # <figure data-trix-attachment='{\"sgid\":\"..."\}'>
82
+ # # <img src="http://example.org/rails/active_storage/.../funny.jpg">
83
+ # # </figure>
84
+ # # </div>
25
85
  def to_trix_html
26
86
  body&.to_trix_html
27
87
  end
@@ -0,0 +1,3 @@
1
+ <figure class="attachment attachment--content">
2
+ <%= content_attachment.attachable %>
3
+ </figure>
@@ -20,6 +20,6 @@ class CreateActionTextTables < ActiveRecord::Migration[6.0]
20
20
  setting = config.options[config.orm][:primary_key_type]
21
21
  primary_key_type = setting || :primary_key
22
22
  foreign_key_type = setting || :bigint
23
- [primary_key_type, foreign_key_type]
23
+ [ primary_key_type, foreign_key_type ]
24
24
  end
25
25
  end