actiontext 7.0.0.alpha2 → 7.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +25 -0
- data/app/assets/javascripts/actiontext.js +27 -7
- data/app/helpers/action_text/tag_helper.rb +14 -2
- data/app/javascript/actiontext/attachment_upload.js +8 -1
- data/lib/action_text/fixture_set.rb +18 -12
- data/lib/action_text/gem_version.rb +1 -1
- data/lib/action_text/plain_text_conversion.rb +31 -2
- data/lib/action_text/serialization.rb +2 -0
- data/lib/generators/action_text/install/install_generator.rb +12 -0
- data/package.json +1 -1
- metadata +31 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5c3bc8decbe98ba953865720f5f520adc3c027006945c8ff12c5e117d288cfaf
|
4
|
+
data.tar.gz: bb4f6cd53d84555f07f19ecc5a0e66e86ec1083daca743111301a62ff72851ae
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6019b83a82205dbb9351b4d7e79fc5d30d84de0031d25ebe5887772ca99b3280c6258262512eac47cff36f4fdaa673de35f2777135438fbc58874a920248856f
|
7
|
+
data.tar.gz: 36f3e55d315bb31e865057589fd95320fa95a4994a3c619285f532000f193089a4e93e8ed71699432979391f486e133bb73d1361dc5f0b7eadefd56e6d832362
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,28 @@
|
|
1
|
+
## Rails 7.0.0 (December 15, 2021) ##
|
2
|
+
|
3
|
+
* No changes.
|
4
|
+
|
5
|
+
|
6
|
+
## Rails 7.0.0.rc3 (December 14, 2021) ##
|
7
|
+
|
8
|
+
* No changes.
|
9
|
+
|
10
|
+
|
11
|
+
## Rails 7.0.0.rc2 (December 14, 2021) ##
|
12
|
+
|
13
|
+
* No changes.
|
14
|
+
|
15
|
+
## Rails 7.0.0.rc1 (December 06, 2021) ##
|
16
|
+
|
17
|
+
* Fix an issue with how nested lists were displayed when converting to plain text
|
18
|
+
|
19
|
+
*Matt Swanson*
|
20
|
+
|
21
|
+
* Allow passing in a custom `direct_upload_url` or `blob_url_template` to `rich_text_area_tag`.
|
22
|
+
|
23
|
+
*Lucas Mansur*
|
24
|
+
|
25
|
+
|
1
26
|
## Rails 7.0.0.alpha2 (September 15, 2021) ##
|
2
27
|
|
3
28
|
* No changes.
|
@@ -506,14 +506,16 @@ var activestorage = {exports: {}};
|
|
506
506
|
}
|
507
507
|
}
|
508
508
|
class BlobRecord {
|
509
|
-
constructor(file, checksum, url) {
|
509
|
+
constructor(file, checksum, url, directUploadToken, attachmentName) {
|
510
510
|
this.file = file;
|
511
511
|
this.attributes = {
|
512
512
|
filename: file.name,
|
513
513
|
content_type: file.type || "application/octet-stream",
|
514
514
|
byte_size: file.size,
|
515
|
-
checksum: checksum
|
515
|
+
checksum: checksum,
|
516
516
|
};
|
517
|
+
this.directUploadToken = directUploadToken;
|
518
|
+
this.attachmentName = attachmentName;
|
517
519
|
this.xhr = new XMLHttpRequest;
|
518
520
|
this.xhr.open("POST", url, true);
|
519
521
|
this.xhr.responseType = "json";
|
@@ -541,7 +543,9 @@ var activestorage = {exports: {}};
|
|
541
543
|
create(callback) {
|
542
544
|
this.callback = callback;
|
543
545
|
this.xhr.send(JSON.stringify({
|
544
|
-
blob: this.attributes
|
546
|
+
blob: this.attributes,
|
547
|
+
direct_upload_token: this.directUploadToken,
|
548
|
+
attachment_name: this.attachmentName
|
545
549
|
}));
|
546
550
|
}
|
547
551
|
requestDidLoad(event) {
|
@@ -599,10 +603,12 @@ var activestorage = {exports: {}};
|
|
599
603
|
}
|
600
604
|
let id = 0;
|
601
605
|
class DirectUpload {
|
602
|
-
constructor(file, url, delegate) {
|
606
|
+
constructor(file, url, directUploadToken, attachmentName, delegate) {
|
603
607
|
this.id = ++id;
|
604
608
|
this.file = file;
|
605
609
|
this.url = url;
|
610
|
+
this.directUploadToken = directUploadToken;
|
611
|
+
this.attachmentName = attachmentName;
|
606
612
|
this.delegate = delegate;
|
607
613
|
}
|
608
614
|
create(callback) {
|
@@ -611,7 +617,7 @@ var activestorage = {exports: {}};
|
|
611
617
|
callback(error);
|
612
618
|
return;
|
613
619
|
}
|
614
|
-
const blob = new BlobRecord(this.file, checksum, this.url);
|
620
|
+
const blob = new BlobRecord(this.file, checksum, this.url, this.directUploadToken, this.attachmentName);
|
615
621
|
notify(this.delegate, "directUploadWillCreateBlobWithXHR", blob.xhr);
|
616
622
|
blob.create((error => {
|
617
623
|
if (error) {
|
@@ -640,7 +646,7 @@ var activestorage = {exports: {}};
|
|
640
646
|
constructor(input, file) {
|
641
647
|
this.input = input;
|
642
648
|
this.file = file;
|
643
|
-
this.directUpload = new DirectUpload(this.file, this.url, this);
|
649
|
+
this.directUpload = new DirectUpload(this.file, this.url, this.directUploadToken, this.attachmentName, this);
|
644
650
|
this.dispatch("initialize");
|
645
651
|
}
|
646
652
|
start(callback) {
|
@@ -671,6 +677,12 @@ var activestorage = {exports: {}};
|
|
671
677
|
get url() {
|
672
678
|
return this.input.getAttribute("data-direct-upload-url");
|
673
679
|
}
|
680
|
+
get directUploadToken() {
|
681
|
+
return this.input.getAttribute("data-direct-upload-token");
|
682
|
+
}
|
683
|
+
get attachmentName() {
|
684
|
+
return this.input.getAttribute("data-direct-upload-attachment-name");
|
685
|
+
}
|
674
686
|
dispatch(name, detail = {}) {
|
675
687
|
detail.file = this.file;
|
676
688
|
detail.id = this.directUpload.id;
|
@@ -830,7 +842,7 @@ class AttachmentUpload {
|
|
830
842
|
constructor(attachment, element) {
|
831
843
|
this.attachment = attachment;
|
832
844
|
this.element = element;
|
833
|
-
this.directUpload = new activestorage.exports.DirectUpload(attachment.file, this.directUploadUrl, this);
|
845
|
+
this.directUpload = new activestorage.exports.DirectUpload(attachment.file, this.directUploadUrl, this.directUploadToken, this.directUploadAttachmentName, this);
|
834
846
|
}
|
835
847
|
|
836
848
|
start() {
|
@@ -865,6 +877,14 @@ class AttachmentUpload {
|
|
865
877
|
return this.element.dataset.directUploadUrl
|
866
878
|
}
|
867
879
|
|
880
|
+
get directUploadToken() {
|
881
|
+
return this.element.dataset.directUploadToken
|
882
|
+
}
|
883
|
+
|
884
|
+
get directUploadAttachmentName() {
|
885
|
+
return this.element.dataset.directUploadAttachmentName
|
886
|
+
}
|
887
|
+
|
868
888
|
get blobUrlTemplate() {
|
869
889
|
return this.element.dataset.blobUrlTemplate
|
870
890
|
}
|
@@ -13,6 +13,8 @@ module ActionText
|
|
13
13
|
# ==== Options
|
14
14
|
# * <tt>:class</tt> - Defaults to "trix-content" so that default styles will be applied.
|
15
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>.
|
16
18
|
#
|
17
19
|
# ==== Example
|
18
20
|
#
|
@@ -27,8 +29,16 @@ module ActionText
|
|
27
29
|
options[:class] ||= "trix-content"
|
28
30
|
|
29
31
|
options[:data] ||= {}
|
30
|
-
options[:data][:direct_upload_url]
|
31
|
-
options[:data][:blob_url_template]
|
32
|
+
options[:data][:direct_upload_url] ||= main_app.rails_direct_uploads_url
|
33
|
+
options[:data][:blob_url_template] ||= main_app.rails_service_blob_url(":signed_id", ":filename")
|
34
|
+
|
35
|
+
class_with_attachment = "ActionText::RichText#embeds"
|
36
|
+
options[:data][:direct_upload_attachment_name] ||= class_with_attachment
|
37
|
+
options[:data][:direct_upload_token] = ActiveStorage::DirectUploadToken.generate_direct_upload_token(
|
38
|
+
class_with_attachment,
|
39
|
+
ActiveStorage::Blob.service.name,
|
40
|
+
session
|
41
|
+
)
|
32
42
|
|
33
43
|
editor_tag = content_tag("trix-editor", "", options)
|
34
44
|
input_tag = hidden_field_tag(name, value.try(:to_trix_html) || value, id: options[:input], form: form)
|
@@ -59,6 +69,8 @@ module ActionView::Helpers
|
|
59
69
|
# ==== Options
|
60
70
|
# * <tt>:class</tt> - Defaults to "trix-content" which ensures default styling is applied.
|
61
71
|
# * <tt>:value</tt> - Adds a default value to the HTML input tag.
|
72
|
+
# * <tt>[:data][:direct_upload_url]</tt> - Defaults to +rails_direct_uploads_url+.
|
73
|
+
# * <tt>[:data][:blob_url_template]</tt> - Defaults to +rails_service_blob_url(":signed_id", ":filename")+.
|
62
74
|
#
|
63
75
|
# ==== Example
|
64
76
|
# form_with(model: @message) do |form|
|
@@ -4,7 +4,7 @@ export class AttachmentUpload {
|
|
4
4
|
constructor(attachment, element) {
|
5
5
|
this.attachment = attachment
|
6
6
|
this.element = element
|
7
|
-
this.directUpload = new DirectUpload(attachment.file, this.directUploadUrl, this)
|
7
|
+
this.directUpload = new DirectUpload(attachment.file, this.directUploadUrl, this.directUploadToken, this.attachmentName, this)
|
8
8
|
}
|
9
9
|
|
10
10
|
start() {
|
@@ -42,4 +42,11 @@ export class AttachmentUpload {
|
|
42
42
|
get blobUrlTemplate() {
|
43
43
|
return this.element.dataset.blobUrlTemplate
|
44
44
|
}
|
45
|
+
|
46
|
+
get directUploadToken() {
|
47
|
+
return this.element.getAttribute("data-direct-upload-token");
|
48
|
+
}
|
49
|
+
get attachmentName() {
|
50
|
+
return this.element.getAttribute("data-direct-upload-attachment-name");
|
51
|
+
}
|
45
52
|
}
|
@@ -10,23 +10,26 @@ module ActionText
|
|
10
10
|
# === YAML
|
11
11
|
#
|
12
12
|
# Like other Active Record-backed models, ActionText::RichText records inherit
|
13
|
-
# from ActiveRecord::Base instances and therefore
|
13
|
+
# from ActiveRecord::Base instances and can therefore be populated by
|
14
14
|
# fixtures.
|
15
15
|
#
|
16
|
-
# Consider
|
17
|
-
# data, as well as fixture data for related ActionText::RichText records:
|
16
|
+
# Consider an <tt>Article</tt> class:
|
18
17
|
#
|
19
|
-
# # app/models/article.rb
|
20
18
|
# class Article < ApplicationRecord
|
21
19
|
# has_rich_text :content
|
22
20
|
# end
|
23
21
|
#
|
24
|
-
#
|
22
|
+
# To declare fixture data for the related <tt>content</tt>, first declare fixture
|
23
|
+
# data for <tt>Article</tt> instances in <tt>test/fixtures/articles.yml</tt>:
|
24
|
+
#
|
25
25
|
# first:
|
26
26
|
# title: An Article
|
27
27
|
#
|
28
|
-
#
|
29
|
-
#
|
28
|
+
# Then declare the <tt>ActionText::RichText</tt> fixture data in
|
29
|
+
# <tt>test/fixtures/action_text/rich_texts.yml</tt>, making sure to declare
|
30
|
+
# each entry's <tt>record:</tt> key as a polymorphic relationship:
|
31
|
+
#
|
32
|
+
# first:
|
30
33
|
# record: first (Article)
|
31
34
|
# name: content
|
32
35
|
# body: <div>Hello, world.</div>
|
@@ -39,18 +42,21 @@ module ActionText
|
|
39
42
|
#
|
40
43
|
# === Examples
|
41
44
|
#
|
42
|
-
# For example, consider a second <tt>Article</tt>
|
43
|
-
#
|
45
|
+
# For example, consider a second <tt>Article</tt> fixture declared in
|
46
|
+
# <tt>test/fixtures/articles.yml</tt>:
|
44
47
|
#
|
45
|
-
# # tests/fixtures/articles.yml
|
46
48
|
# second:
|
47
49
|
# title: Another Article
|
48
50
|
#
|
49
|
-
#
|
50
|
-
#
|
51
|
+
# You can attach a mention of <tt>articles(:first)</tt> to <tt>second</tt>'s
|
52
|
+
# <tt>content</tt> by embedding a call to <tt>ActionText::FixtureSet.attachment</tt>
|
53
|
+
# in the <tt>body:</tt> value in <tt>test/fixtures/action_text/rich_texts.yml</tt>:
|
54
|
+
#
|
55
|
+
# second:
|
51
56
|
# record: second (Article)
|
52
57
|
# name: content
|
53
58
|
# body: <div>Hello, <%= ActionText::FixtureSet.attachment("articles", :first) %></div>
|
59
|
+
#
|
54
60
|
def self.attachment(fixture_set_name, label, column_type: :integer)
|
55
61
|
signed_global_id = ActiveRecord::FixtureSet.signed_global_id fixture_set_name, label,
|
56
62
|
column_type: column_type, for: ActionText::Attachable::LOCATOR_NAME
|
@@ -33,10 +33,18 @@ module ActionText
|
|
33
33
|
"#{remove_trailing_newlines(plain_text_for_node_children(node))}\n\n"
|
34
34
|
end
|
35
35
|
|
36
|
-
%i[ h1 p
|
36
|
+
%i[ h1 p ].each do |element|
|
37
37
|
alias_method :"plain_text_for_#{element}_node", :plain_text_for_block
|
38
38
|
end
|
39
39
|
|
40
|
+
def plain_text_for_list(node, index)
|
41
|
+
"#{break_if_nested_list(node, plain_text_for_block(node))}"
|
42
|
+
end
|
43
|
+
|
44
|
+
%i[ ul ol ].each do |element|
|
45
|
+
alias_method :"plain_text_for_#{element}_node", :plain_text_for_list
|
46
|
+
end
|
47
|
+
|
40
48
|
def plain_text_for_br_node(node, index)
|
41
49
|
"\n"
|
42
50
|
end
|
@@ -61,7 +69,9 @@ module ActionText
|
|
61
69
|
def plain_text_for_li_node(node, index)
|
62
70
|
bullet = bullet_for_li_node(node, index)
|
63
71
|
text = remove_trailing_newlines(plain_text_for_node_children(node))
|
64
|
-
|
72
|
+
indentation = indentation_for_li_node(node)
|
73
|
+
|
74
|
+
"#{indentation}#{bullet} #{text}\n"
|
65
75
|
end
|
66
76
|
|
67
77
|
def remove_trailing_newlines(text)
|
@@ -79,5 +89,24 @@ module ActionText
|
|
79
89
|
def list_node_name_for_li_node(node)
|
80
90
|
node.ancestors.lazy.map(&:name).grep(/^[uo]l$/).first
|
81
91
|
end
|
92
|
+
|
93
|
+
def indentation_for_li_node(node)
|
94
|
+
depth = list_node_depth_for_node(node)
|
95
|
+
if depth > 1
|
96
|
+
" " * (depth - 1)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def list_node_depth_for_node(node)
|
101
|
+
node.ancestors.map(&:name).grep(/^[uo]l$/).count
|
102
|
+
end
|
103
|
+
|
104
|
+
def break_if_nested_list(node, text)
|
105
|
+
if list_node_depth_for_node(node) > 0
|
106
|
+
"\n#{text}"
|
107
|
+
else
|
108
|
+
text
|
109
|
+
end
|
110
|
+
end
|
82
111
|
end
|
83
112
|
end
|
@@ -32,8 +32,20 @@ module ActionText
|
|
32
32
|
end
|
33
33
|
|
34
34
|
def create_actiontext_files
|
35
|
+
destination = Pathname(destination_root)
|
36
|
+
|
35
37
|
template "actiontext.css", "app/assets/stylesheets/actiontext.css"
|
36
38
|
|
39
|
+
unless destination.join("app/assets/application.css").exist?
|
40
|
+
if (stylesheets = Dir.glob "#{destination_root}/app/assets/stylesheets/application.*.{scss,css}").length > 0
|
41
|
+
insert_into_file stylesheets.first.to_s, %(@import 'actiontext.css';)
|
42
|
+
else
|
43
|
+
say <<~INSTRUCTIONS, :green
|
44
|
+
To use the Trix editor, you must require 'app/assets/stylesheets/actiontext.css' in your base stylesheet.
|
45
|
+
INSTRUCTIONS
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
37
49
|
gem_root = "#{__dir__}/../../../.."
|
38
50
|
|
39
51
|
copy_file "#{gem_root}/app/views/active_storage/blobs/_blob.html.erb",
|
data/package.json
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: actiontext
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 7.0.0
|
4
|
+
version: 7.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Javan Makhmali
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2021-
|
13
|
+
date: 2021-12-15 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: activesupport
|
@@ -18,56 +18,56 @@ dependencies:
|
|
18
18
|
requirements:
|
19
19
|
- - '='
|
20
20
|
- !ruby/object:Gem::Version
|
21
|
-
version: 7.0.0
|
21
|
+
version: 7.0.0
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
24
|
version_requirements: !ruby/object:Gem::Requirement
|
25
25
|
requirements:
|
26
26
|
- - '='
|
27
27
|
- !ruby/object:Gem::Version
|
28
|
-
version: 7.0.0
|
28
|
+
version: 7.0.0
|
29
29
|
- !ruby/object:Gem::Dependency
|
30
30
|
name: activerecord
|
31
31
|
requirement: !ruby/object:Gem::Requirement
|
32
32
|
requirements:
|
33
33
|
- - '='
|
34
34
|
- !ruby/object:Gem::Version
|
35
|
-
version: 7.0.0
|
35
|
+
version: 7.0.0
|
36
36
|
type: :runtime
|
37
37
|
prerelease: false
|
38
38
|
version_requirements: !ruby/object:Gem::Requirement
|
39
39
|
requirements:
|
40
40
|
- - '='
|
41
41
|
- !ruby/object:Gem::Version
|
42
|
-
version: 7.0.0
|
42
|
+
version: 7.0.0
|
43
43
|
- !ruby/object:Gem::Dependency
|
44
44
|
name: activestorage
|
45
45
|
requirement: !ruby/object:Gem::Requirement
|
46
46
|
requirements:
|
47
47
|
- - '='
|
48
48
|
- !ruby/object:Gem::Version
|
49
|
-
version: 7.0.0
|
49
|
+
version: 7.0.0
|
50
50
|
type: :runtime
|
51
51
|
prerelease: false
|
52
52
|
version_requirements: !ruby/object:Gem::Requirement
|
53
53
|
requirements:
|
54
54
|
- - '='
|
55
55
|
- !ruby/object:Gem::Version
|
56
|
-
version: 7.0.0
|
56
|
+
version: 7.0.0
|
57
57
|
- !ruby/object:Gem::Dependency
|
58
58
|
name: actionpack
|
59
59
|
requirement: !ruby/object:Gem::Requirement
|
60
60
|
requirements:
|
61
61
|
- - '='
|
62
62
|
- !ruby/object:Gem::Version
|
63
|
-
version: 7.0.0
|
63
|
+
version: 7.0.0
|
64
64
|
type: :runtime
|
65
65
|
prerelease: false
|
66
66
|
version_requirements: !ruby/object:Gem::Requirement
|
67
67
|
requirements:
|
68
68
|
- - '='
|
69
69
|
- !ruby/object:Gem::Version
|
70
|
-
version: 7.0.0
|
70
|
+
version: 7.0.0
|
71
71
|
- !ruby/object:Gem::Dependency
|
72
72
|
name: nokogiri
|
73
73
|
requirement: !ruby/object:Gem::Requirement
|
@@ -82,6 +82,20 @@ dependencies:
|
|
82
82
|
- - ">="
|
83
83
|
- !ruby/object:Gem::Version
|
84
84
|
version: 1.8.5
|
85
|
+
- !ruby/object:Gem::Dependency
|
86
|
+
name: globalid
|
87
|
+
requirement: !ruby/object:Gem::Requirement
|
88
|
+
requirements:
|
89
|
+
- - ">="
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: 0.6.0
|
92
|
+
type: :runtime
|
93
|
+
prerelease: false
|
94
|
+
version_requirements: !ruby/object:Gem::Requirement
|
95
|
+
requirements:
|
96
|
+
- - ">="
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: 0.6.0
|
85
99
|
description: Edit and display rich text in Rails applications.
|
86
100
|
email:
|
87
101
|
- javan@javan.us
|
@@ -146,10 +160,11 @@ licenses:
|
|
146
160
|
- MIT
|
147
161
|
metadata:
|
148
162
|
bug_tracker_uri: https://github.com/rails/rails/issues
|
149
|
-
changelog_uri: https://github.com/rails/rails/blob/v7.0.0
|
150
|
-
documentation_uri: https://api.rubyonrails.org/v7.0.0
|
163
|
+
changelog_uri: https://github.com/rails/rails/blob/v7.0.0/actiontext/CHANGELOG.md
|
164
|
+
documentation_uri: https://api.rubyonrails.org/v7.0.0/
|
151
165
|
mailing_list_uri: https://discuss.rubyonrails.org/c/rubyonrails-talk
|
152
|
-
source_code_uri: https://github.com/rails/rails/tree/v7.0.0
|
166
|
+
source_code_uri: https://github.com/rails/rails/tree/v7.0.0/actiontext
|
167
|
+
rubygems_mfa_required: 'true'
|
153
168
|
post_install_message:
|
154
169
|
rdoc_options: []
|
155
170
|
require_paths:
|
@@ -161,11 +176,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
161
176
|
version: 2.7.0
|
162
177
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
163
178
|
requirements:
|
164
|
-
- - "
|
179
|
+
- - ">="
|
165
180
|
- !ruby/object:Gem::Version
|
166
|
-
version:
|
181
|
+
version: '0'
|
167
182
|
requirements: []
|
168
|
-
rubygems_version: 3.
|
183
|
+
rubygems_version: 3.2.32
|
169
184
|
signing_key:
|
170
185
|
specification_version: 4
|
171
186
|
summary: Rich text framework.
|