marksmith 0.1.0 → 0.1.2
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.
- checksums.yaml +4 -4
- data/README.md +86 -16
- data/app/assets/javascripts/list_continuation_controller-full.esm.js +1 -1
- data/app/assets/javascripts/list_continuation_controller-no-stimulus.esm.js +1 -1
- data/app/assets/javascripts/marksmith_controller-full.esm.js +10 -1
- data/app/assets/javascripts/marksmith_controller-no-stimulus.esm.js +10 -1
- data/app/frontend/entrypoints/javascript/controllers/marksmith_controller.js +9 -0
- data/app/views/marksmith/shared/_editor.html.erb +21 -4
- data/lib/generators/marksmith/install_generator.rb +15 -0
- data/lib/generators/marksmith/templates/initializer/marksmith.tt +4 -0
- data/lib/marksmith/configuration.rb +16 -0
- data/lib/marksmith/engine.rb +12 -4
- data/lib/marksmith/version.rb +1 -1
- data/lib/marksmith.rb +1 -0
- metadata +8 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5018de3478a97ddcec156c4245851720d0ea86d36a2002ab82ba9a145f6739cc
|
4
|
+
data.tar.gz: 7fb9f7f2a8f702abad17476695f14bf65669af942609c2dffe1531bb71137f30
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 813d6e4f66ac1a41c20afc5d1d6815d8695163badf4cb45ddbf49a1da394eb3c9436677610a61bf00bbf67e961abab9a6e5b89b1ccf61f203d82650d36f97292
|
7
|
+
data.tar.gz: 10b74b2a3af7f5ee6ecea2d76d54efe3d91d9784c4f3bd38ba807a828f36a79ae722deaab0285c8b9027660b452380f35df2b84af945971b85ed7199a4bd3a91
|
data/README.md
CHANGED
@@ -8,6 +8,11 @@ It supports Active Storage attachments and comes with a built-in mardown preview
|
|
8
8
|
|
9
9
|

|
10
10
|
|
11
|
+
> [!WARNING]
|
12
|
+
> Marksmith is at the initial stage of development. It's nearing a beta release, but the API might change and bugs are expected. Please continue to use the library and report any issues in the GitHub repo.
|
13
|
+
|
14
|
+
Temporary live demo here, under the description field: [https://main.avodemo.com/avo/resources/projects/new](https://main.avodemo.com/avo/resources/projects/new)
|
15
|
+
|
11
16
|
## Usage
|
12
17
|
|
13
18
|
```erb
|
@@ -16,7 +21,7 @@ It supports Active Storage attachments and comes with a built-in mardown preview
|
|
16
21
|
|
17
22
|
## Installation
|
18
23
|
|
19
|
-
|
24
|
+
#### 1. Add `marksmith` to your `Gemfile`
|
20
25
|
|
21
26
|
Have Bundler add it by running this command:
|
22
27
|
|
@@ -33,20 +38,27 @@ Add this line to your application's Gemfile:
|
|
33
38
|
gem "marksmith"
|
34
39
|
```
|
35
40
|
|
36
|
-
|
41
|
+
#### 2. Install the NPM package to import the StimulusJS controller.
|
37
42
|
|
38
|
-
Install the package.
|
43
|
+
Install the package from npmjs.org.
|
39
44
|
|
40
45
|
```bash
|
41
46
|
$ yarn add @avo-hq/marksmith
|
42
47
|
```
|
43
48
|
|
44
|
-
|
49
|
+
Or pin it using importmap.
|
50
|
+
|
51
|
+
```bash
|
52
|
+
bin/importmap pin @avo-hq/marksmith
|
53
|
+
```
|
54
|
+
|
55
|
+
Import and register the controllers in your application. The `ListContinuationController` is optional and only needed if you want to have continued lists in your markdown.
|
45
56
|
|
46
57
|
```js
|
47
|
-
import { MarksmithController } from '@avo-hq/marksmith'
|
58
|
+
import { MarksmithController, ListContinuationController } from '@avo-hq/marksmith'
|
48
59
|
|
49
60
|
application.register('marksmith', MarksmithController)
|
61
|
+
application.register('list-continuation', ListContinuationController)
|
50
62
|
```
|
51
63
|
|
52
64
|
> [!NOTE]
|
@@ -66,28 +78,78 @@ import { MarksmithController } from '@avo-hq/marksmith/core'
|
|
66
78
|
application.register('marksmith', MarksmithController)
|
67
79
|
```
|
68
80
|
|
69
|
-
|
81
|
+
#### 3. Add the style tag to your `application.html` layout
|
70
82
|
|
71
83
|
```erb
|
72
84
|
<%= stylesheet_link_tag "marksmith" %>
|
73
85
|
```
|
74
86
|
|
75
|
-
|
87
|
+
#### 4. Use it
|
76
88
|
|
77
89
|
Use a form helper tag or attach it to your form builder.
|
78
90
|
|
79
91
|
```erb
|
80
92
|
<%= marksmith_tag :body, value: "### This is important" %>
|
81
93
|
or
|
82
|
-
<%=
|
94
|
+
<%= form.marksmith :body %>
|
83
95
|
```
|
84
96
|
|
85
|
-
##
|
97
|
+
## Configuration
|
98
|
+
|
99
|
+
Marksmith accepts a few configuration options.
|
100
|
+
|
101
|
+
### Field options
|
86
102
|
|
87
103
|
The field supports a few of the regular options like `disabled`, `placeholder`, `autofocus`, `style`, `class`, `rows`, `data`, and `value`, but also a custom one.
|
88
104
|
|
89
105
|
`extra_preview_params` - Sends extra params to the preview renderer.
|
90
106
|
|
107
|
+
`enable_file_uploads` - Whether to enable file uploads.
|
108
|
+
|
109
|
+
`upload_url` - The URL to use for file uploads. If not provided, the editor will use the `rails_direct_uploads_url` helper.
|
110
|
+
|
111
|
+
```erb
|
112
|
+
<%= marksmith_tag :body,
|
113
|
+
disabled: true,
|
114
|
+
placeholder: "Write your best markdown here.",
|
115
|
+
extra_preview_params: { foo: "bar" },
|
116
|
+
enable_file_uploads: true,
|
117
|
+
upload_url: nil
|
118
|
+
%>
|
119
|
+
```
|
120
|
+
|
121
|
+
### Eject configuration file
|
122
|
+
|
123
|
+
Marksmith comes with a default configuration file that you can eject to your app.
|
124
|
+
|
125
|
+
```bash
|
126
|
+
bin/rails generate marksmith:install
|
127
|
+
```
|
128
|
+
|
129
|
+
This will create a `config/initializers/marksmith.rb` file in your app.
|
130
|
+
|
131
|
+
### Mount path
|
132
|
+
|
133
|
+
The engine is mounted by default at `/marksmith`. You can change it by setting `Marksmith.configuration.mount_path` to a different path.
|
134
|
+
|
135
|
+
```ruby
|
136
|
+
# config/initializers/marksmith.rb
|
137
|
+
Marksmith.configure do |config|
|
138
|
+
config.mount_path = "/markdown"
|
139
|
+
end
|
140
|
+
```
|
141
|
+
|
142
|
+
### Mounting the engine
|
143
|
+
|
144
|
+
The engine is mounted by default, but you can disable it by setting `Marksmith.configuration.automatically_mount_engine` to `false` and then manually mount the engine in your `routes.rb` file.
|
145
|
+
|
146
|
+
```ruby
|
147
|
+
# config/routes.rb
|
148
|
+
Rails.application.routes.draw do
|
149
|
+
mount Marksmith::Engine => Marksmith.configuration.mount_path
|
150
|
+
end
|
151
|
+
```
|
152
|
+
|
91
153
|
## Built-in preview renderer
|
92
154
|
|
93
155
|
The renderer is powered by [`Redcarpet`](https://github.com/vmg/redcarpet).
|
@@ -96,16 +158,18 @@ It supports basic styles for headings, `strong`, `italic` and others.
|
|
96
158
|
In your `show.html.erb` view or the place where you want to render the compiled markup use the `marksmithed` helper and it will run the content through the renderer.
|
97
159
|
|
98
160
|
```erb
|
99
|
-
|
161
|
+
<%== marksmithed post.body %>
|
100
162
|
```
|
101
163
|
|
102
|
-
|
164
|
+
> [!WARNING]
|
165
|
+
> Using the `<%==` tag will output the raw HTML, so ensure you sanitize the content to avoid XSS attacks.
|
166
|
+
>
|
167
|
+
> See how we do it [here](https://github.com/avo-hq/avo/blob/main/app/views/marksmith/shared/_rendered_body.html.erb#L2).
|
168
|
+
> ```ruby
|
169
|
+
> # sample sanitization
|
170
|
+
> sanitize(body, tags: %w(table th tr td span) + ActionView::Helpers::SanitizeHelper.sanitizer_vendor.safe_list_sanitizer.allowed_tags.to_a)
|
171
|
+
> ```
|
103
172
|
|
104
|
-
It should be as simple as running this command and have it pinned in your `importmap.rb` file.
|
105
|
-
|
106
|
-
```bash
|
107
|
-
bin/importmap pin @avo-hq/marksmith
|
108
|
-
```
|
109
173
|
|
110
174
|
## Active Storage
|
111
175
|
|
@@ -128,6 +192,12 @@ application.register('marksmith', MarksmithController)
|
|
128
192
|
application.register('list-continuation', ListContinuationController)
|
129
193
|
```
|
130
194
|
|
195
|
+
## Who uses Marksmith?
|
196
|
+
|
197
|
+
- [Avo](https://avohq.io) - Ruby on Rails Code-Based App Builder Framework
|
198
|
+
|
199
|
+
*Open a PR and add your project here*
|
200
|
+
|
131
201
|
## Contributing
|
132
202
|
|
133
203
|
Contribution directions go here.
|
@@ -1,5 +1,5 @@
|
|
1
1
|
/*!
|
2
|
-
Marksmith 0.1.
|
2
|
+
Marksmith 0.1.2
|
3
3
|
*/
|
4
4
|
var MarksmithController = (function () {
|
5
5
|
'use strict';
|
@@ -2827,10 +2827,15 @@ var MarksmithController = (function () {
|
|
2827
2827
|
fieldId: String,
|
2828
2828
|
galleryEnabled: { type: Boolean, default: false },
|
2829
2829
|
galleryOpenPath: String,
|
2830
|
+
fileUploadsEnabled: { type: Boolean, default: true },
|
2830
2831
|
}
|
2831
2832
|
|
2832
2833
|
static targets = ['fieldContainer', 'fieldElement', 'previewElement', 'writeTabButton', 'previewTabButton', 'toolbar']
|
2833
2834
|
|
2835
|
+
get #fileUploadsDisabled() {
|
2836
|
+
return !this.fileUploadsEnabledValue
|
2837
|
+
}
|
2838
|
+
|
2834
2839
|
connect() {
|
2835
2840
|
subscribe(this.fieldContainerTarget, { defaultPlainTextPaste: { urlLinks: true } });
|
2836
2841
|
}
|
@@ -2878,11 +2883,15 @@ var MarksmithController = (function () {
|
|
2878
2883
|
}
|
2879
2884
|
|
2880
2885
|
dropUpload(event) {
|
2886
|
+
if (this.#fileUploadsDisabled) return
|
2887
|
+
|
2881
2888
|
event.preventDefault();
|
2882
2889
|
this.#uploadFiles(event.dataTransfer.files);
|
2883
2890
|
}
|
2884
2891
|
|
2885
2892
|
pasteUpload(event) {
|
2893
|
+
if (this.#fileUploadsDisabled) return
|
2894
|
+
|
2886
2895
|
if (!event.clipboardData.files.length) return
|
2887
2896
|
|
2888
2897
|
event.preventDefault();
|
@@ -1,5 +1,5 @@
|
|
1
1
|
/*!
|
2
|
-
Marksmith 0.1.
|
2
|
+
Marksmith 0.1.2
|
3
3
|
*/
|
4
4
|
var MarksmithController = (function (stimulus) {
|
5
5
|
'use strict';
|
@@ -2337,10 +2337,15 @@ var MarksmithController = (function (stimulus) {
|
|
2337
2337
|
fieldId: String,
|
2338
2338
|
galleryEnabled: { type: Boolean, default: false },
|
2339
2339
|
galleryOpenPath: String,
|
2340
|
+
fileUploadsEnabled: { type: Boolean, default: true },
|
2340
2341
|
}
|
2341
2342
|
|
2342
2343
|
static targets = ['fieldContainer', 'fieldElement', 'previewElement', 'writeTabButton', 'previewTabButton', 'toolbar']
|
2343
2344
|
|
2345
|
+
get #fileUploadsDisabled() {
|
2346
|
+
return !this.fileUploadsEnabledValue
|
2347
|
+
}
|
2348
|
+
|
2344
2349
|
connect() {
|
2345
2350
|
subscribe(this.fieldContainerTarget, { defaultPlainTextPaste: { urlLinks: true } });
|
2346
2351
|
}
|
@@ -2388,11 +2393,15 @@ var MarksmithController = (function (stimulus) {
|
|
2388
2393
|
}
|
2389
2394
|
|
2390
2395
|
dropUpload(event) {
|
2396
|
+
if (this.#fileUploadsDisabled) return
|
2397
|
+
|
2391
2398
|
event.preventDefault();
|
2392
2399
|
this.#uploadFiles(event.dataTransfer.files);
|
2393
2400
|
}
|
2394
2401
|
|
2395
2402
|
pasteUpload(event) {
|
2403
|
+
if (this.#fileUploadsDisabled) return
|
2404
|
+
|
2396
2405
|
if (!event.clipboardData.files.length) return
|
2397
2406
|
|
2398
2407
|
event.preventDefault();
|
@@ -17,10 +17,15 @@ export default class extends Controller {
|
|
17
17
|
fieldId: String,
|
18
18
|
galleryEnabled: { type: Boolean, default: false },
|
19
19
|
galleryOpenPath: String,
|
20
|
+
fileUploadsEnabled: { type: Boolean, default: true },
|
20
21
|
}
|
21
22
|
|
22
23
|
static targets = ['fieldContainer', 'fieldElement', 'previewElement', 'writeTabButton', 'previewTabButton', 'toolbar']
|
23
24
|
|
25
|
+
get #fileUploadsDisabled() {
|
26
|
+
return !this.fileUploadsEnabledValue
|
27
|
+
}
|
28
|
+
|
24
29
|
connect() {
|
25
30
|
subscribe(this.fieldContainerTarget, { defaultPlainTextPaste: { urlLinks: true } })
|
26
31
|
}
|
@@ -68,11 +73,15 @@ export default class extends Controller {
|
|
68
73
|
}
|
69
74
|
|
70
75
|
dropUpload(event) {
|
76
|
+
if (this.#fileUploadsDisabled) return
|
77
|
+
|
71
78
|
event.preventDefault()
|
72
79
|
this.#uploadFiles(event.dataTransfer.files)
|
73
80
|
}
|
74
81
|
|
75
82
|
pasteUpload(event) {
|
83
|
+
if (this.#fileUploadsDisabled) return
|
84
|
+
|
76
85
|
if (!event.clipboardData.files.length) return
|
77
86
|
|
78
87
|
event.preventDefault()
|
@@ -13,6 +13,20 @@
|
|
13
13
|
local_assigns[:value] || nil
|
14
14
|
end
|
15
15
|
extra_preview_params = local_assigns[:extra_preview_params] || {}
|
16
|
+
upload_url = if local_assigns[:upload_url].present?
|
17
|
+
local_assigns[:upload_url]
|
18
|
+
elsif defined?(ActiveStorage)
|
19
|
+
main_app.rails_direct_uploads_url
|
20
|
+
end
|
21
|
+
|
22
|
+
enable_file_uploads = if upload_url.blank?
|
23
|
+
false
|
24
|
+
elsif local_assigns[:enable_file_uploads].nil?
|
25
|
+
true
|
26
|
+
else
|
27
|
+
local_assigns[:enable_file_uploads]
|
28
|
+
end
|
29
|
+
|
16
30
|
|
17
31
|
# Used by Avo and other adapters to enable the gallery link.
|
18
32
|
gallery_enabled = local_assigns.dig(:gallery, :enabled) || false
|
@@ -35,8 +49,9 @@
|
|
35
49
|
",
|
36
50
|
unique_selector: ".#{@input_id}", # used to pinpoint the exact element in which to insert the attachment
|
37
51
|
marksmith_preview_url_value: marksmith.markdown_previews_path,
|
52
|
+
marksmith_file_uploads_enabled_value: enable_file_uploads,
|
38
53
|
marksmith_active_tab_class: "bg-white",
|
39
|
-
marksmith_attach_url_value:
|
54
|
+
marksmith_attach_url_value: upload_url,
|
40
55
|
marksmith_extra_preview_params_value: extra_preview_params.as_json,
|
41
56
|
**local_assigns.fetch(:controller_data_attributes, {})
|
42
57
|
} do %>
|
@@ -69,7 +84,7 @@
|
|
69
84
|
<%= content_tag :div, class: "ms:flex ms:flex-1 ms:flex-col ms:size-full", data: { marksmith_target: "fieldContainer" } do %>
|
70
85
|
<%= text_area_tag field_name, value,
|
71
86
|
id: name,
|
72
|
-
class: class_names("ms:flex ms:flex-1 ms:rounded ms:border-none ms:resize-y ms:focus:outline-none ms:font-mono ms:focus:ring-0 ms:leading-normal ms:p-2", classes),
|
87
|
+
class: class_names("ms:flex ms:flex-1 ms:rounded ms:border-none ms:resize-y ms:focus:outline-none ms:font-mono ms:focus:ring-0 ms:leading-normal ms:p-2 ms:text-sm", classes),
|
73
88
|
rows: rows,
|
74
89
|
data: {
|
75
90
|
action: "drop->marksmith#dropUpload paste->marksmith#pasteUpload",
|
@@ -85,8 +100,10 @@
|
|
85
100
|
<%= link_to "https://docs.github.com/github/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax", target: "_blank", class: class_names("ms:flex ms:items-center ms:text-neutral-800 ms:no-underline", toolbar_button_classes) do %>
|
86
101
|
<%= image_tag asset_path("marksmith/svgs/markdown.svg"), class: "ms:inline ms:size-4 ms:mr-1" %> <%= t("marksmith.markdown_is_supported").humanize %>
|
87
102
|
<% end %>
|
88
|
-
|
89
|
-
<%=
|
103
|
+
<% if enable_file_uploads %>
|
104
|
+
<%= button_tag data: { action: "click->marksmith#buttonUpload" }, class: class_names("ms:bg-none ms:border-none ms:bg-transparent ms:text-neutral-600 ms:items-center ms:flex", toolbar_button_classes) do %>
|
105
|
+
<%= image_tag asset_path("marksmith/svgs/paperclip.svg"), class: "ms:inline ms:size-4 ms:mr-1" %> <%= t("marksmith.upload_files").humanize %>
|
106
|
+
<% end %>
|
90
107
|
<% end %>
|
91
108
|
<% if gallery_enabled %>
|
92
109
|
<%= link_to gallery_full_path, data: { turbo_frame: gallery_turbo_frame }, class: class_names("ms:flex ms:items-center ms:text-neutral-800 ms:no-underline", toolbar_button_classes) do %>
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require "rails/generators"
|
2
|
+
|
3
|
+
module Marksmith
|
4
|
+
module Generators
|
5
|
+
class InstallGenerator < Rails::Generators::Base
|
6
|
+
source_root File.expand_path("templates", __dir__)
|
7
|
+
|
8
|
+
desc "Creates a Marksmith initializer."
|
9
|
+
|
10
|
+
def create_initializer_file
|
11
|
+
template "initializer/marksmith.tt", "config/initializers/marksmith.rb"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Marksmith
|
2
|
+
class Configuration
|
3
|
+
include ActiveSupport::Configurable
|
4
|
+
|
5
|
+
config_accessor(:automatically_mount_engine) { true }
|
6
|
+
config_accessor(:mount_path) { "/marksmith" }
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.configuration
|
10
|
+
@configuration ||= Configuration.new
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.configure
|
14
|
+
yield configuration
|
15
|
+
end
|
16
|
+
end
|
data/lib/marksmith/engine.rb
CHANGED
@@ -17,6 +17,14 @@ module Marksmith
|
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
+
initializer "marksmith.routes" do |app|
|
21
|
+
if Marksmith.configuration.automatically_mount_engine
|
22
|
+
app.routes.append do
|
23
|
+
mount Marksmith::Engine => Marksmith.configuration.mount_path
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
20
28
|
initializer "marksmith.assets.precompile" do |app|
|
21
29
|
if Rails.application.config.respond_to?(:assets)
|
22
30
|
# The manifest will expose the asset files to the main app.
|
@@ -24,14 +32,14 @@ module Marksmith
|
|
24
32
|
end
|
25
33
|
end
|
26
34
|
|
35
|
+
generators do |app|
|
36
|
+
Rails::Generators.configure! app.config.generators
|
37
|
+
end
|
38
|
+
|
27
39
|
initializer "avo-markdown_field.init" do |app|
|
28
40
|
if defined?(Avo)
|
29
41
|
require "marksmith/fields/markdown_field"
|
30
42
|
|
31
|
-
app.routes.append do
|
32
|
-
mount Marksmith::Engine => "/marksmith"
|
33
|
-
end
|
34
|
-
|
35
43
|
ActiveSupport.on_load(:avo_boot) do
|
36
44
|
Avo.plugin_manager.register :marksmith_field
|
37
45
|
|
data/lib/marksmith/version.rb
CHANGED
data/lib/marksmith.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: marksmith
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Adrian Marin
|
@@ -11,19 +11,19 @@ cert_chain: []
|
|
11
11
|
date: 2025-02-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: activesupport
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: '0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
26
|
+
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: redcarpet
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -96,7 +96,10 @@ files:
|
|
96
96
|
- config/locales/marksmith.en.yml
|
97
97
|
- config/routes.rb
|
98
98
|
- config/vite.json
|
99
|
+
- lib/generators/marksmith/install_generator.rb
|
100
|
+
- lib/generators/marksmith/templates/initializer/marksmith.tt
|
99
101
|
- lib/marksmith.rb
|
102
|
+
- lib/marksmith/configuration.rb
|
100
103
|
- lib/marksmith/engine.rb
|
101
104
|
- lib/marksmith/fields/markdown_field.rb
|
102
105
|
- lib/marksmith/helper.rb
|
@@ -124,7 +127,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
124
127
|
- !ruby/object:Gem::Version
|
125
128
|
version: '0'
|
126
129
|
requirements: []
|
127
|
-
rubygems_version: 3.5.
|
130
|
+
rubygems_version: 3.5.22
|
128
131
|
signing_key:
|
129
132
|
specification_version: 4
|
130
133
|
summary: Marksmith is a GitHub-style markdown editor for Ruby on Rails applications.
|