actiontext 6.1.7.9 → 7.0.0.alpha1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of actiontext might be problematic. Click here for more details.

Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +19 -195
  3. data/MIT-LICENSE +1 -1
  4. data/README.md +4 -0
  5. data/app/assets/javascripts/actiontext.js +880 -0
  6. data/app/assets/javascripts/trix.js +5278 -0
  7. data/app/assets/stylesheets/trix.css +375 -0
  8. data/app/helpers/action_text/content_helper.rb +17 -3
  9. data/app/helpers/action_text/tag_helper.rb +5 -7
  10. data/app/models/action_text/encrypted_rich_text.rb +9 -0
  11. data/app/models/action_text/record.rb +1 -1
  12. data/app/models/action_text/rich_text.rb +4 -0
  13. data/app/views/action_text/contents/_content.html.erb +1 -0
  14. data/app/views/layouts/action_text/contents/_content.html.erb +3 -0
  15. data/db/migrate/20180528164100_create_action_text_tables.rb +14 -2
  16. data/lib/action_text/attachable.rb +4 -0
  17. data/lib/action_text/attachment.rb +4 -4
  18. data/lib/action_text/attachment_gallery.rb +14 -9
  19. data/lib/action_text/attachments/caching.rb +1 -1
  20. data/lib/action_text/attachments/minification.rb +1 -1
  21. data/lib/action_text/attribute.rb +18 -2
  22. data/lib/action_text/content.rb +7 -3
  23. data/lib/action_text/encryption.rb +38 -0
  24. data/lib/action_text/engine.rb +14 -0
  25. data/lib/action_text/fixture_set.rb +49 -0
  26. data/lib/action_text/gem_version.rb +4 -4
  27. data/lib/action_text/plain_text_conversion.rb +1 -6
  28. data/lib/action_text/rendering.rb +1 -1
  29. data/lib/action_text/serialization.rb +0 -2
  30. data/lib/action_text/trix_attachment.rb +3 -3
  31. data/lib/action_text.rb +1 -0
  32. data/lib/generators/action_text/install/install_generator.rb +28 -35
  33. data/lib/generators/action_text/install/templates/actiontext.css +35 -0
  34. data/package.json +13 -3
  35. metadata +25 -20
  36. data/app/views/action_text/content/_layout.html.erb +0 -3
  37. data/lib/generators/action_text/install/templates/actiontext.scss +0 -36
@@ -0,0 +1,375 @@
1
+ @charset "UTF-8";
2
+ /*
3
+ Trix 1.3.1
4
+ Copyright © 2020 Basecamp, LLC
5
+ http://trix-editor.org/*/
6
+ trix-editor {
7
+ border: 1px solid #bbb;
8
+ border-radius: 3px;
9
+ margin: 0;
10
+ padding: 0.4em 0.6em;
11
+ min-height: 5em;
12
+ outline: none; }
13
+ trix-toolbar * {
14
+ box-sizing: border-box; }
15
+ trix-toolbar .trix-button-row {
16
+ display: flex;
17
+ flex-wrap: nowrap;
18
+ justify-content: space-between;
19
+ overflow-x: auto; }
20
+ trix-toolbar .trix-button-group {
21
+ display: flex;
22
+ margin-bottom: 10px;
23
+ border: 1px solid #bbb;
24
+ border-top-color: #ccc;
25
+ border-bottom-color: #888;
26
+ border-radius: 3px; }
27
+ trix-toolbar .trix-button-group:not(:first-child) {
28
+ margin-left: 1.5vw; }
29
+ @media (max-device-width: 768px) {
30
+ trix-toolbar .trix-button-group:not(:first-child) {
31
+ margin-left: 0; } }
32
+ trix-toolbar .trix-button-group-spacer {
33
+ flex-grow: 1; }
34
+ @media (max-device-width: 768px) {
35
+ trix-toolbar .trix-button-group-spacer {
36
+ display: none; } }
37
+ trix-toolbar .trix-button {
38
+ position: relative;
39
+ float: left;
40
+ color: rgba(0, 0, 0, 0.6);
41
+ font-size: 0.75em;
42
+ font-weight: 600;
43
+ white-space: nowrap;
44
+ padding: 0 0.5em;
45
+ margin: 0;
46
+ outline: none;
47
+ border: none;
48
+ border-bottom: 1px solid #ddd;
49
+ border-radius: 0;
50
+ background: transparent; }
51
+ trix-toolbar .trix-button:not(:first-child) {
52
+ border-left: 1px solid #ccc; }
53
+ trix-toolbar .trix-button.trix-active {
54
+ background: #cbeefa;
55
+ color: black; }
56
+ trix-toolbar .trix-button:not(:disabled) {
57
+ cursor: pointer; }
58
+ trix-toolbar .trix-button:disabled {
59
+ color: rgba(0, 0, 0, 0.125); }
60
+ @media (max-device-width: 768px) {
61
+ trix-toolbar .trix-button {
62
+ letter-spacing: -0.01em;
63
+ padding: 0 0.3em; } }
64
+ trix-toolbar .trix-button--icon {
65
+ font-size: inherit;
66
+ width: 2.6em;
67
+ height: 1.6em;
68
+ max-width: calc(0.8em + 4vw);
69
+ text-indent: -9999px; }
70
+ @media (max-device-width: 768px) {
71
+ trix-toolbar .trix-button--icon {
72
+ height: 2em;
73
+ max-width: calc(0.8em + 3.5vw); } }
74
+ trix-toolbar .trix-button--icon::before {
75
+ display: inline-block;
76
+ position: absolute;
77
+ top: 0;
78
+ right: 0;
79
+ bottom: 0;
80
+ left: 0;
81
+ opacity: 0.6;
82
+ content: "";
83
+ background-position: center;
84
+ background-repeat: no-repeat;
85
+ background-size: contain; }
86
+ @media (max-device-width: 768px) {
87
+ trix-toolbar .trix-button--icon::before {
88
+ right: 6%;
89
+ left: 6%; } }
90
+ trix-toolbar .trix-button--icon.trix-active::before {
91
+ opacity: 1; }
92
+ trix-toolbar .trix-button--icon:disabled::before {
93
+ opacity: 0.125; }
94
+ 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);
96
+ top: 8%;
97
+ bottom: 4%; }
98
+ 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); }
100
+ 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); }
102
+ 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); }
104
+ 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); }
106
+ 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); }
108
+ 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); }
110
+ 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); }
112
+ 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); }
114
+ 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); }
116
+ 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); }
118
+ 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); }
120
+ 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); }
122
+ 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); }
124
+ trix-toolbar .trix-dialogs {
125
+ position: relative; }
126
+ trix-toolbar .trix-dialog {
127
+ position: absolute;
128
+ top: 0;
129
+ left: 0;
130
+ right: 0;
131
+ font-size: 0.75em;
132
+ padding: 15px 10px;
133
+ background: #fff;
134
+ box-shadow: 0 0.3em 1em #ccc;
135
+ border-top: 2px solid #888;
136
+ border-radius: 5px;
137
+ z-index: 5; }
138
+ trix-toolbar .trix-input--dialog {
139
+ font-size: inherit;
140
+ font-weight: normal;
141
+ padding: 0.5em 0.8em;
142
+ margin: 0 10px 0 0;
143
+ border-radius: 3px;
144
+ border: 1px solid #bbb;
145
+ background-color: #fff;
146
+ box-shadow: none;
147
+ outline: none;
148
+ -webkit-appearance: none;
149
+ -moz-appearance: none; }
150
+ trix-toolbar .trix-input--dialog.validate:invalid {
151
+ box-shadow: #F00 0px 0px 1.5px 1px; }
152
+ trix-toolbar .trix-button--dialog {
153
+ font-size: inherit;
154
+ padding: 0.5em;
155
+ border-bottom: none; }
156
+ trix-toolbar .trix-dialog--link {
157
+ max-width: 600px; }
158
+ trix-toolbar .trix-dialog__link-fields {
159
+ display: flex;
160
+ align-items: baseline; }
161
+ trix-toolbar .trix-dialog__link-fields .trix-input {
162
+ flex: 1; }
163
+ trix-toolbar .trix-dialog__link-fields .trix-button-group {
164
+ flex: 0 0 content;
165
+ margin: 0; }
166
+ trix-editor [data-trix-mutable]:not(.attachment__caption-editor) {
167
+ -webkit-user-select: none;
168
+ -moz-user-select: none;
169
+ -ms-user-select: none;
170
+ user-select: none; }
171
+
172
+ trix-editor [data-trix-mutable]::-moz-selection,
173
+ trix-editor [data-trix-cursor-target]::-moz-selection, trix-editor [data-trix-mutable] ::-moz-selection {
174
+ background: none; }
175
+ trix-editor [data-trix-mutable]::selection,
176
+ trix-editor [data-trix-cursor-target]::selection, trix-editor [data-trix-mutable] ::selection {
177
+ background: none; }
178
+
179
+ trix-editor [data-trix-mutable].attachment__caption-editor:focus::-moz-selection {
180
+ background: highlight; }
181
+ trix-editor [data-trix-mutable].attachment__caption-editor:focus::selection {
182
+ background: highlight; }
183
+
184
+ trix-editor [data-trix-mutable].attachment.attachment--file {
185
+ box-shadow: 0 0 0 2px highlight;
186
+ border-color: transparent; }
187
+ trix-editor [data-trix-mutable].attachment img {
188
+ box-shadow: 0 0 0 2px highlight; }
189
+ trix-editor .attachment {
190
+ position: relative; }
191
+ trix-editor .attachment:hover {
192
+ cursor: default; }
193
+ trix-editor .attachment--preview .attachment__caption:hover {
194
+ cursor: text; }
195
+ trix-editor .attachment__progress {
196
+ position: absolute;
197
+ z-index: 1;
198
+ height: 20px;
199
+ top: calc(50% - 10px);
200
+ left: 5%;
201
+ width: 90%;
202
+ opacity: 0.9;
203
+ transition: opacity 200ms ease-in; }
204
+ trix-editor .attachment__progress[value="100"] {
205
+ opacity: 0; }
206
+ trix-editor .attachment__caption-editor {
207
+ display: inline-block;
208
+ width: 100%;
209
+ margin: 0;
210
+ padding: 0;
211
+ font-size: inherit;
212
+ font-family: inherit;
213
+ line-height: inherit;
214
+ color: inherit;
215
+ text-align: center;
216
+ vertical-align: top;
217
+ border: none;
218
+ outline: none;
219
+ -webkit-appearance: none;
220
+ -moz-appearance: none; }
221
+ trix-editor .attachment__toolbar {
222
+ position: absolute;
223
+ z-index: 1;
224
+ top: -0.9em;
225
+ left: 0;
226
+ width: 100%;
227
+ text-align: center; }
228
+ trix-editor .trix-button-group {
229
+ display: inline-flex; }
230
+ trix-editor .trix-button {
231
+ position: relative;
232
+ float: left;
233
+ color: #666;
234
+ white-space: nowrap;
235
+ font-size: 80%;
236
+ padding: 0 0.8em;
237
+ margin: 0;
238
+ outline: none;
239
+ border: none;
240
+ border-radius: 0;
241
+ background: transparent; }
242
+ trix-editor .trix-button:not(:first-child) {
243
+ border-left: 1px solid #ccc; }
244
+ trix-editor .trix-button.trix-active {
245
+ background: #cbeefa; }
246
+ trix-editor .trix-button:not(:disabled) {
247
+ cursor: pointer; }
248
+ trix-editor .trix-button--remove {
249
+ text-indent: -9999px;
250
+ display: inline-block;
251
+ padding: 0;
252
+ outline: none;
253
+ width: 1.8em;
254
+ height: 1.8em;
255
+ line-height: 1.8em;
256
+ border-radius: 50%;
257
+ background-color: #fff;
258
+ border: 2px solid highlight;
259
+ box-shadow: 1px 1px 6px rgba(0, 0, 0, 0.25); }
260
+ trix-editor .trix-button--remove::before {
261
+ display: inline-block;
262
+ position: absolute;
263
+ top: 0;
264
+ right: 0;
265
+ bottom: 0;
266
+ left: 0;
267
+ opacity: 0.7;
268
+ 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);
270
+ background-position: center;
271
+ background-repeat: no-repeat;
272
+ background-size: 90%; }
273
+ trix-editor .trix-button--remove:hover {
274
+ border-color: #333; }
275
+ trix-editor .trix-button--remove:hover::before {
276
+ opacity: 1; }
277
+ trix-editor .attachment__metadata-container {
278
+ position: relative; }
279
+ trix-editor .attachment__metadata {
280
+ position: absolute;
281
+ left: 50%;
282
+ top: 2em;
283
+ transform: translate(-50%, 0);
284
+ max-width: 90%;
285
+ padding: 0.1em 0.6em;
286
+ font-size: 0.8em;
287
+ color: #fff;
288
+ background-color: rgba(0, 0, 0, 0.7);
289
+ border-radius: 3px; }
290
+ trix-editor .attachment__metadata .attachment__name {
291
+ display: inline-block;
292
+ max-width: 100%;
293
+ vertical-align: bottom;
294
+ overflow: hidden;
295
+ text-overflow: ellipsis;
296
+ white-space: nowrap; }
297
+ trix-editor .attachment__metadata .attachment__size {
298
+ margin-left: 0.2em;
299
+ white-space: nowrap; }
300
+ @charset "UTF-8";
301
+ .trix-content {
302
+ line-height: 1.5; }
303
+ .trix-content * {
304
+ box-sizing: border-box;
305
+ margin: 0;
306
+ padding: 0; }
307
+ .trix-content h1 {
308
+ font-size: 1.2em;
309
+ line-height: 1.2; }
310
+ .trix-content blockquote {
311
+ border: 0 solid #ccc;
312
+ border-left-width: 0.3em;
313
+ margin-left: 0.3em;
314
+ padding-left: 0.6em; }
315
+ .trix-content [dir=rtl] blockquote,
316
+ .trix-content blockquote[dir=rtl] {
317
+ border-width: 0;
318
+ border-right-width: 0.3em;
319
+ margin-right: 0.3em;
320
+ padding-right: 0.6em; }
321
+ .trix-content li {
322
+ margin-left: 1em; }
323
+ .trix-content [dir=rtl] li {
324
+ margin-right: 1em; }
325
+ .trix-content pre {
326
+ display: inline-block;
327
+ width: 100%;
328
+ vertical-align: top;
329
+ font-family: monospace;
330
+ font-size: 0.9em;
331
+ padding: 0.5em;
332
+ white-space: pre;
333
+ background-color: #eee;
334
+ overflow-x: auto; }
335
+ .trix-content img {
336
+ max-width: 100%;
337
+ height: auto; }
338
+ .trix-content .attachment {
339
+ display: inline-block;
340
+ position: relative;
341
+ max-width: 100%; }
342
+ .trix-content .attachment a {
343
+ color: inherit;
344
+ text-decoration: none; }
345
+ .trix-content .attachment a:hover, .trix-content .attachment a:visited:hover {
346
+ color: inherit; }
347
+ .trix-content .attachment__caption {
348
+ text-align: center; }
349
+ .trix-content .attachment__caption .attachment__name + .attachment__size::before {
350
+ content: ' · '; }
351
+ .trix-content .attachment--preview {
352
+ width: 100%;
353
+ text-align: center; }
354
+ .trix-content .attachment--preview .attachment__caption {
355
+ color: #666;
356
+ font-size: 0.9em;
357
+ line-height: 1.2; }
358
+ .trix-content .attachment--file {
359
+ color: #333;
360
+ line-height: 1;
361
+ margin: 0 2px 2px 2px;
362
+ padding: 0.4em 1em;
363
+ border: 1px solid #bbb;
364
+ border-radius: 5px; }
365
+ .trix-content .attachment-gallery {
366
+ display: flex;
367
+ flex-wrap: wrap;
368
+ position: relative; }
369
+ .trix-content .attachment-gallery .attachment {
370
+ flex: 1 0 33%;
371
+ padding: 0 0.5em;
372
+ max-width: 33%; }
373
+ .trix-content .attachment-gallery.attachment-gallery--2 .attachment, .trix-content .attachment-gallery.attachment-gallery--4 .attachment {
374
+ flex-basis: 50%;
375
+ max-width: 50%; }
@@ -5,7 +5,7 @@ require "rails-html-sanitizer"
5
5
  module ActionText
6
6
  module ContentHelper
7
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" ] }
8
+ mattr_accessor(:allowed_tags) { sanitizer.class.allowed_tags + [ ActionText::Attachment.tag_name, "figure", "figcaption" ] }
9
9
  mattr_accessor(:allowed_attributes) { sanitizer.class.allowed_attributes + ActionText::Attachment::ATTRIBUTES }
10
10
  mattr_accessor(:scrubber)
11
11
 
@@ -22,17 +22,31 @@ module ActionText
22
22
  content.render_attachments do |attachment|
23
23
  unless attachment.in?(content.gallery_attachments)
24
24
  attachment.node.tap do |node|
25
- node.inner_html = render(attachment, in_gallery: false).chomp
25
+ node.inner_html = render_action_text_attachment attachment, locals: { in_gallery: false }
26
26
  end
27
27
  end
28
28
  end.render_attachment_galleries do |attachment_gallery|
29
29
  render(layout: attachment_gallery, object: attachment_gallery) do
30
30
  attachment_gallery.attachments.map do |attachment|
31
- attachment.node.inner_html = render(attachment, in_gallery: true).chomp
31
+ attachment.node.inner_html = render_action_text_attachment attachment, locals: { in_gallery: true }
32
32
  attachment.to_html
33
33
  end.join.html_safe
34
34
  end.chomp
35
35
  end
36
36
  end
37
+
38
+ def render_action_text_attachment(attachment, locals: {}) # :nodoc:
39
+ options = { locals: locals, object: attachment, partial: attachment }
40
+
41
+ if attachment.respond_to?(:to_attachable_partial_path)
42
+ options[:partial] = attachment.to_attachable_partial_path
43
+ end
44
+
45
+ if attachment.respond_to?(:model_name)
46
+ options[:as] = attachment.model_name.element
47
+ end
48
+
49
+ render(**options).chomp
50
+ end
37
51
  end
38
52
  end
@@ -11,7 +11,8 @@ module ActionText
11
11
  # that Trix will write to on changes, so the content will be sent on form submissions.
12
12
  #
13
13
  # ==== Options
14
- # * <tt>:class</tt> - Defaults to "trix-content" which ensures default styling is applied.
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.
15
16
  #
16
17
  # ==== Example
17
18
  #
@@ -20,6 +21,7 @@ module ActionText
20
21
  # # <trix-editor id="content" input="trix_input_post_1" class="trix-content" ...></trix-editor>
21
22
  def rich_text_area_tag(name, value = nil, options = {})
22
23
  options = options.symbolize_keys
24
+ form = options.delete(:form)
23
25
 
24
26
  options[:input] ||= "trix_input_#{ActionText::TagHelper.id += 1}"
25
27
  options[:class] ||= "trix-content"
@@ -29,7 +31,7 @@ module ActionText
29
31
  options[:data][:blob_url_template] = main_app.rails_service_blob_url(":signed_id", ":filename")
30
32
 
31
33
  editor_tag = content_tag("trix-editor", "", options)
32
- input_tag = hidden_field_tag(name, value, id: options[:input])
34
+ input_tag = hidden_field_tag(name, value.try(:to_trix_html) || value, id: options[:input], form: form)
33
35
 
34
36
  input_tag + editor_tag
35
37
  end
@@ -46,11 +48,7 @@ module ActionView::Helpers
46
48
  options = @options.stringify_keys
47
49
  add_default_name_and_id(options)
48
50
  options["input"] ||= dom_id(object, [options["id"], :trix_input].compact.join("_")) if object
49
- @template_object.rich_text_area_tag(options.delete("name"), options.fetch("value") { editable_value }, options.except("value"))
50
- end
51
-
52
- def editable_value
53
- value&.body.try(:to_trix_html)
51
+ @template_object.rich_text_area_tag(options.delete("name"), options.fetch("value") { value }, options.except("value"))
54
52
  end
55
53
  end
56
54
 
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActionText
4
+ class EncryptedRichText < RichText
5
+ self.table_name = "action_text_rich_texts"
6
+
7
+ encrypts :body
8
+ end
9
+ end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActionText
4
- class Record < ActiveRecord::Base #:nodoc:
4
+ class Record < ActiveRecord::Base # :nodoc:
5
5
  self.abstract_class = true
6
6
  end
7
7
  end
@@ -22,6 +22,10 @@ module ActionText
22
22
  body&.to_plain_text.to_s
23
23
  end
24
24
 
25
+ def to_trix_html
26
+ body&.to_trix_html
27
+ end
28
+
25
29
  delegate :blank?, :empty?, :present?, to: :to_plain_text
26
30
  end
27
31
  end
@@ -0,0 +1 @@
1
+ <%= render_action_text_content(content) %>
@@ -0,0 +1,3 @@
1
+ <div class="trix-content">
2
+ <%= yield -%>
3
+ </div>
@@ -1,13 +1,25 @@
1
1
  class CreateActionTextTables < ActiveRecord::Migration[6.0]
2
2
  def change
3
- create_table :action_text_rich_texts do |t|
3
+ # Use Active Record's configured type for primary and foreign keys
4
+ primary_key_type, foreign_key_type = primary_and_foreign_key_types
5
+
6
+ create_table :action_text_rich_texts, id: primary_key_type do |t|
4
7
  t.string :name, null: false
5
8
  t.text :body, size: :long
6
- t.references :record, null: false, polymorphic: true, index: false
9
+ t.references :record, null: false, polymorphic: true, index: false, type: foreign_key_type
7
10
 
8
11
  t.timestamps
9
12
 
10
13
  t.index [ :record_type, :record_id, :name ], name: "index_action_text_rich_texts_uniqueness", unique: true
11
14
  end
12
15
  end
16
+
17
+ private
18
+ def primary_and_foreign_key_types
19
+ config = Rails.configuration.generators
20
+ setting = config.options[config.orm][:primary_key_type]
21
+ primary_key_type = setting || :primary_key
22
+ foreign_key_type = setting || :bigint
23
+ [primary_key_type, foreign_key_type]
24
+ end
13
25
  end
@@ -71,6 +71,10 @@ module ActionText
71
71
  to_partial_path
72
72
  end
73
73
 
74
+ def to_attachable_partial_path
75
+ to_partial_path
76
+ end
77
+
74
78
  def to_rich_text_attributes(attributes = {})
75
79
  attributes.dup.tap do |attrs|
76
80
  attrs[:sgid] = attachable_sgid
@@ -6,8 +6,8 @@ module ActionText
6
6
  class Attachment
7
7
  include Attachments::TrixConversion, Attachments::Minification, Attachments::Caching
8
8
 
9
- TAG_NAME = "action-text-attachment"
10
- SELECTOR = TAG_NAME
9
+ mattr_accessor :tag_name, default: "action-text-attachment"
10
+
11
11
  ATTRIBUTES = %w( sgid content-type url href filename filesize width height previewable presentation caption )
12
12
 
13
13
  class << self
@@ -20,7 +20,7 @@ module ActionText
20
20
  end
21
21
 
22
22
  def from_attachables(attachables)
23
- Array(attachables).map { |attachable| from_attachable(attachable) }.compact
23
+ Array(attachables).filter_map { |attachable| from_attachable(attachable) }
24
24
  end
25
25
 
26
26
  def from_attachable(attachable, attributes = {})
@@ -38,7 +38,7 @@ module ActionText
38
38
  private
39
39
  def node_from_attributes(attributes)
40
40
  if attributes = process_attributes(attributes).presence
41
- ActionText::HtmlConversion.create_element(TAG_NAME, attributes)
41
+ ActionText::HtmlConversion.create_element(tag_name, attributes)
42
42
  end
43
43
  end
44
44
 
@@ -4,6 +4,9 @@ module ActionText
4
4
  class AttachmentGallery
5
5
  include ActiveModel::Model
6
6
 
7
+ TAG_NAME = "div"
8
+ private_constant :TAG_NAME
9
+
7
10
  class << self
8
11
  def fragment_by_canonicalizing_attachment_galleries(content)
9
12
  fragment_by_replacing_attachment_gallery_nodes(content) do |node|
@@ -20,12 +23,12 @@ module ActionText
20
23
  end
21
24
 
22
25
  def find_attachment_gallery_nodes(content)
23
- Fragment.wrap(content).find_all(SELECTOR).select do |node|
26
+ Fragment.wrap(content).find_all(selector).select do |node|
24
27
  node.children.all? do |child|
25
28
  if child.text?
26
29
  /\A(\n|\ )*\z/.match?(child.text)
27
30
  else
28
- child.matches? ATTACHMENT_SELECTOR
31
+ child.matches? attachment_selector
29
32
  end
30
33
  end
31
34
  end
@@ -34,6 +37,14 @@ module ActionText
34
37
  def from_node(node)
35
38
  new(node)
36
39
  end
40
+
41
+ def attachment_selector
42
+ "#{ActionText::Attachment.tag_name}[presentation=gallery]"
43
+ end
44
+
45
+ def selector
46
+ "#{TAG_NAME}:has(#{attachment_selector} + #{attachment_selector})"
47
+ end
37
48
  end
38
49
 
39
50
  attr_reader :node
@@ -43,7 +54,7 @@ module ActionText
43
54
  end
44
55
 
45
56
  def attachments
46
- @attachments ||= node.css(ATTACHMENT_SELECTOR).map do |node|
57
+ @attachments ||= node.css(ActionText::AttachmentGallery.attachment_selector).map do |node|
47
58
  ActionText::Attachment.from_node(node).with_full_attributes
48
59
  end
49
60
  end
@@ -55,11 +66,5 @@ module ActionText
55
66
  def inspect
56
67
  "#<#{self.class.name} size=#{size.inspect}>"
57
68
  end
58
-
59
- TAG_NAME = "div"
60
- ATTACHMENT_SELECTOR = "#{ActionText::Attachment::SELECTOR}[presentation=gallery]"
61
- SELECTOR = "#{TAG_NAME}:has(#{ATTACHMENT_SELECTOR} + #{ATTACHMENT_SELECTOR})"
62
-
63
- private_constant :TAG_NAME, :ATTACHMENT_SELECTOR, :SELECTOR
64
69
  end
65
70
  end
@@ -9,7 +9,7 @@ module ActionText
9
9
 
10
10
  private
11
11
  def cache_digest
12
- Digest::SHA256.hexdigest(node.to_s)
12
+ OpenSSL::Digest::SHA256.hexdigest(node.to_s)
13
13
  end
14
14
  end
15
15
  end
@@ -7,7 +7,7 @@ module ActionText
7
7
 
8
8
  class_methods do
9
9
  def fragment_by_minifying_attachments(content)
10
- Fragment.wrap(content).replace(ActionText::Attachment::SELECTOR) do |node|
10
+ Fragment.wrap(content).replace(ActionText::Attachment.tag_name) do |node|
11
11
  node.tap { |n| n.inner_html = "" }
12
12
  end
13
13
  end