marksmith 0.0.4

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 +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +60 -0
  4. data/Rakefile +8 -0
  5. data/app/assets/config/marksmith_manifest.js +2 -0
  6. data/app/assets/images/marksmith/svgs/bold.svg +3 -0
  7. data/app/assets/images/marksmith/svgs/code.svg +3 -0
  8. data/app/assets/images/marksmith/svgs/color-swatch copy.svg +3 -0
  9. data/app/assets/images/marksmith/svgs/color-swatch.svg +3 -0
  10. data/app/assets/images/marksmith/svgs/heading.svg +1 -0
  11. data/app/assets/images/marksmith/svgs/italic.svg +3 -0
  12. data/app/assets/images/marksmith/svgs/link copy.svg +3 -0
  13. data/app/assets/images/marksmith/svgs/link.svg +3 -0
  14. data/app/assets/images/marksmith/svgs/list-bullet.svg +3 -0
  15. data/app/assets/images/marksmith/svgs/list-todo.svg +1 -0
  16. data/app/assets/images/marksmith/svgs/numbered-list.svg +3 -0
  17. data/app/assets/images/marksmith/svgs/photo.svg +3 -0
  18. data/app/assets/images/marksmith/svgs/quote.svg +1 -0
  19. data/app/assets/stylesheets/marksmith/application.css +15 -0
  20. data/app/assets/stylesheets/marksmith.css +517 -0
  21. data/app/controllers/marksmith/application_controller.rb +4 -0
  22. data/app/controllers/marksmith/markdown_previews_controller.rb +8 -0
  23. data/app/frontend/entrypoints/application.css +6 -0
  24. data/app/frontend/entrypoints/application.js +29 -0
  25. data/app/frontend/entrypoints/javascript/controllers/application.js +9 -0
  26. data/app/frontend/entrypoints/javascript/controllers/index.js +7 -0
  27. data/app/frontend/entrypoints/javascript/controllers/marksmith_controller.js +111 -0
  28. data/app/helpers/marksmith/application_helper.rb +4 -0
  29. data/app/helpers/marksmith/helper.rb +21 -0
  30. data/app/jobs/marksmith/application_job.rb +4 -0
  31. data/app/mailers/marksmith/application_mailer.rb +6 -0
  32. data/app/models/marksmith/application_record.rb +5 -0
  33. data/app/models/marksmith/renderer.rb +23 -0
  34. data/app/views/layouts/marksmith/application.html.erb +17 -0
  35. data/app/views/marksmith/markdown_previews/create.turbo_stream.erb +6 -0
  36. data/app/views/marksmith/shared/_editor.html.erb +120 -0
  37. data/app/views/marksmith/shared/_rendered_body.html.erb +3 -0
  38. data/config/locales/marksmith.en.yml +33 -0
  39. data/config/routes.rb +3 -0
  40. data/config/vite.json +16 -0
  41. data/lib/marksmith/engine.rb +25 -0
  42. data/lib/marksmith/version.rb +3 -0
  43. data/lib/marksmith.rb +5 -0
  44. data/lib/tasks/marksmith_tasks.rake +4 -0
  45. metadata +131 -0
@@ -0,0 +1,111 @@
1
+ /* eslint-disable camelcase */
2
+ import '@github/markdown-toolbar-element'
3
+ import { Controller } from '@hotwired/stimulus'
4
+ import { DirectUpload } from '@rails/activestorage'
5
+ import { post } from '@rails/request.js'
6
+ import { subscribe } from '@github/paste-markdown'
7
+
8
+ // upload code from Jeremy Smith's blog post
9
+ // https://hybrd.co/posts/github-issue-style-file-uploader-using-stimulus-and-active-storage
10
+
11
+ // Connects to data-controller="marksmith"
12
+ export default class extends Controller {
13
+ static values = {
14
+ attachUrl: String,
15
+ previewUrl: String,
16
+ resourceClass: String,
17
+ fieldId: String,
18
+ }
19
+
20
+ static targets = ['fieldElement', 'previewElement', 'writeTabButton', 'previewTabButton', 'toolbar']
21
+
22
+ connect() {
23
+ subscribe(this.fieldElementTarget, { defaultPlainTextPaste: { urlLinks: true } })
24
+ }
25
+
26
+ switchToWrite(event) {
27
+ event.preventDefault()
28
+
29
+ // toggle buttons
30
+ this.writeTabButtonTarget.classList.add('ms:hidden')
31
+ this.previewTabButtonTarget.classList.remove('ms:hidden')
32
+
33
+ // toggle write/preview buttons
34
+ this.fieldElementTarget.classList.remove('ms:hidden')
35
+ this.previewElementTarget.classList.add('ms:hidden')
36
+
37
+ // toggle the toolbar back
38
+ this.toolbarTarget.classList.remove('ms:hidden')
39
+ }
40
+
41
+ switchToPreview(event) {
42
+ event.preventDefault()
43
+
44
+ post(this.previewUrlValue, {
45
+ body: {
46
+ body: this.fieldElementTarget.value,
47
+ resource_class: this.resourceClassValue,
48
+ field_id: this.fieldIdValue,
49
+ element_id: this.previewElementTarget.id,
50
+ },
51
+ responseKind: 'turbo-stream',
52
+ })
53
+
54
+ // set the min height to the field element height
55
+ this.previewElementTarget.style.minHeight = `${this.fieldElementTarget.offsetHeight}px`
56
+
57
+ // toggle buttons
58
+ this.writeTabButtonTarget.classList.remove('ms:hidden')
59
+ this.previewTabButtonTarget.classList.add('ms:hidden')
60
+
61
+ // toggle elements
62
+ this.fieldElementTarget.classList.add('ms:hidden')
63
+ this.previewElementTarget.classList.remove('ms:hidden')
64
+
65
+ // toggle the toolbar
66
+ this.toolbarTarget.classList.add('ms:hidden')
67
+ }
68
+
69
+ dropUpload(event) {
70
+ event.preventDefault()
71
+ this.uploadFiles(event.dataTransfer.files)
72
+ }
73
+
74
+ pasteUpload(event) {
75
+ if (!event.clipboardData.files.length) return
76
+
77
+ event.preventDefault()
78
+ this.uploadFiles(event.clipboardData.files)
79
+ }
80
+
81
+ uploadFiles(files) {
82
+ Array.from(files).forEach((file) => this.uploadFile(file))
83
+ }
84
+
85
+ uploadFile(file) {
86
+ const upload = new DirectUpload(file, this.attachUrlValue)
87
+
88
+ upload.create((error, blob) => {
89
+ if (error) {
90
+ console.log('Error', error)
91
+ } else {
92
+ const text = this.markdownLink(blob)
93
+ const start = this.fieldElementTarget.selectionStart
94
+ const end = this.fieldElementTarget.selectionEnd
95
+ this.fieldElementTarget.setRangeText(text, start, end)
96
+ }
97
+ })
98
+ }
99
+
100
+ markdownLink(blob) {
101
+ const { filename } = blob
102
+ const url = `/rails/active_storage/blobs/${blob.signed_id}/${filename}`
103
+ const prefix = (this.isImage(blob.content_type) ? '!' : '')
104
+
105
+ return `${prefix}[${filename}](${url})\n`
106
+ }
107
+
108
+ isImage(contentType) {
109
+ return ['image/jpeg', 'image/gif', 'image/png'].includes(contentType)
110
+ }
111
+ }
@@ -0,0 +1,4 @@
1
+ module Marksmith
2
+ module ApplicationHelper
3
+ end
4
+ end
@@ -0,0 +1,21 @@
1
+ module Marksmith
2
+ module Helper
3
+ def marksmithed(body)
4
+ Marksmith::Renderer.new.renderer.render(body)
5
+ end
6
+
7
+ def marksmith_tag(name, **kwargs, &block)
8
+ render partial: "marksmith/shared/editor", locals: { name: name, **kwargs }
9
+ end
10
+
11
+ def marksmith_asset_tags(*args, **kwargs)
12
+ stylesheet_link_tag("marksmith", *args, **kwargs) +
13
+ javascript_include_tag("marksmith.esm.js", *args, **kwargs)
14
+ end
15
+
16
+ # TODO: maybe inline svgs in the future
17
+ def svg(name, options = {})
18
+ image_tag asset_path("marksmith/svgs/#{name}.svg"), options
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,4 @@
1
+ module Marksmith
2
+ class ApplicationJob < ActiveJob::Base
3
+ end
4
+ end
@@ -0,0 +1,6 @@
1
+ module Marksmith
2
+ class ApplicationMailer < ActionMailer::Base
3
+ default from: "from@example.com"
4
+ layout "mailer"
5
+ end
6
+ end
@@ -0,0 +1,5 @@
1
+ module Marksmith
2
+ class ApplicationRecord < ActiveRecord::Base
3
+ self.abstract_class = true
4
+ end
5
+ end
@@ -0,0 +1,23 @@
1
+ require "redcarpet"
2
+ require "rouge"
3
+
4
+ module Marksmith
5
+ class Renderer
6
+ def renderer
7
+ ::Redcarpet::Markdown.new(
8
+ ::Redcarpet::Render::HTML,
9
+ tables: true,
10
+ lax_spacing: true,
11
+ fenced_code_blocks: true,
12
+ space_after_headers: true,
13
+ hard_wrap: true,
14
+ autolink: true,
15
+ strikethrough: true,
16
+ underline: true,
17
+ highlight: true,
18
+ quote: true,
19
+ with_toc_data: true
20
+ )
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,17 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Marksmith</title>
5
+ <%= csrf_meta_tags %>
6
+ <%= csp_meta_tag %>
7
+
8
+ <%= yield :head %>
9
+
10
+ <%= stylesheet_link_tag "marksmith/application", media: "all" %>
11
+ </head>
12
+ <body>
13
+
14
+ <%= yield %>
15
+
16
+ </body>
17
+ </html>
@@ -0,0 +1,6 @@
1
+ <%= turbo_stream.update params[:element_id] do %>
2
+ <div class="ms:px-3 ms:py-2">
3
+ <%= render "marksmith/shared/rendered_body", body: @body %>
4
+ </div>
5
+ <% end %>
6
+
@@ -0,0 +1,120 @@
1
+ <%
2
+ data_attributes = local_assigns[:data] || {}
3
+ disabled = local_assigns[:disabled] || false
4
+ placeholder = local_assigns[:placeholder] || nil
5
+ autofocus = local_assigns[:autofocus] || false
6
+ style = local_assigns[:style] || nil
7
+ classes = local_assigns[:classes] || nil
8
+ rows = local_assigns[:rows] || 15
9
+ %>
10
+ <%= content_tag :div,
11
+ class: "ms:flex ms:flex-col ms:w-full ms:border ms:border-zinc-300 ms:rounded ms:@container ms:group ms:focus-within:border-zinc-500",
12
+ data: {
13
+ controller: "marksmith",
14
+ marksmith_preview_url_value: marksmith.markdown_previews_path,
15
+ marksmith_active_tab_class: "bg-white",
16
+ marksmith_attach_url_value: rails_direct_uploads_url,
17
+ marksmith_resource_class_value: @resource.class.name,
18
+ marksmith_field_id_value: name,
19
+ } do %>
20
+ <% button_classes = class_names("ms:flex ms:items:center ms:cursor-pointer ms:py-1 ms:px-1.5 ms:hover:bg-zinc-200 ms:rounded") %>
21
+ <% toggle_button_classes = class_names(button_classes, "ms:border-0 ms:bg-none") %>
22
+ <div class="ms:flex-1 ms:flex-col-reverse ms:@md:flex-row ms:grow ms:flex ms:justify-bewteen ms:bg-zinc-50 ms:rounded ms:px-2 ms:py-1 ms:gap-y-1">
23
+ <div class="ms:flex-1 ms:flex ms:items:center">
24
+ <button class="<%= toggle_button_classes %>" data-action="click->marksmith#switchToPreview" data-marksmith-target="previewTabButton">
25
+ <%= t('marksmith.preview').humanize %>
26
+ </button>
27
+ <button class="<%= toggle_button_classes %> ms:hidden ms:bg-zinc-200" data-action="click->marksmith#switchToWrite" data-marksmith-target="writeTabButton">
28
+ <%= t('marksmith.write').humanize %>
29
+ </button>
30
+ </div>
31
+
32
+ <markdown-toolbar for="<%= name %>" class="<%= class_names("ms:flex ms:flex-wrap", "ms:pointer-events-none": disabled) %>" data-marksmith-target="toolbar">
33
+ <md-bold
34
+ title="<%= t('marksmith.bold').humanize %>"
35
+ class="<%= button_classes %>"
36
+ >
37
+ <%= svg "bold", class: "ms:inline ms:size-4" %>
38
+ </md-bold>
39
+ <md-header
40
+ title="<%= t('marksmith.heading').humanize %>"
41
+ class="<%= button_classes %>"
42
+ >
43
+ <%= svg "heading", class: "ms:inline ms:size-4" %>
44
+ </md-header>
45
+ <md-italic
46
+ title="<%= t('marksmith.italic').humanize %>"
47
+ class="<%= button_classes %>"
48
+ >
49
+ <%= svg "italic", class: "ms:inline ms:size-4" %>
50
+ </md-italic>
51
+ <md-quote
52
+ title="<%= t('marksmith.quote').humanize %>"
53
+ class="<%= button_classes %>"
54
+ >
55
+ <%= svg "quote", class: "ms:inline ms:size-4" %>
56
+ </md-quote>
57
+ <md-code
58
+ title="<%= t('marksmith.code').humanize %>"
59
+ class="<%= button_classes %>"
60
+ >
61
+ <%= svg "code", class: "ms:inline ms:size-4" %>
62
+ </md-code>
63
+ <md-link
64
+ title="<%= t('marksmith.link').humanize %>"
65
+ class="<%= button_classes %>"
66
+ >
67
+ <%= svg "link", class: "ms:inline ms:size-4" %>
68
+ </md-link>
69
+ <md-image
70
+ title="<%= t('marksmith.image').humanize %>"
71
+ class="<%= button_classes %>"
72
+ >
73
+ <%= svg "photo", class: "ms:inline ms:size-4" %>
74
+ </md-image>
75
+ <md-unordered-list
76
+ title="<%= t('marksmith.unordered_list').humanize %>"
77
+ class="<%= button_classes %>"
78
+ >
79
+ <%= svg "list-bullet", class: "ms:inline ms:size-4" %>
80
+ </md-unordered-list>
81
+ <md-ordered-list
82
+ title="<%= t('marksmith.ordered_list').humanize %>"
83
+ class="<%= button_classes %>"
84
+ >
85
+ <%= svg "numbered-list", class: "ms:inline ms:size-4" %>
86
+ </md-ordered-list>
87
+ <md-task-list
88
+ title="<%= t('marksmith.task_list').humanize %>"
89
+ class="<%= button_classes %>"
90
+ >
91
+ <%= svg "list-todo", class: "ms:inline ms:size-4" %>
92
+ </md-task-list>
93
+ </markdown-toolbar>
94
+ </div>
95
+
96
+ <div class="ms:border-t ms:border-zinc-300 ms:flex">
97
+ <%= form.text_area name,
98
+ id: name,
99
+ # value: @field.value,
100
+ class: class_names("ms:flex ms:flex-1 ms:rounded ms:border-none ms:py-2 ms:px-3 ms:focus:outline-none", classes),
101
+ rows: rows,
102
+ data: {
103
+ marksmith_target: "fieldElement",
104
+ action: "drop->marksmith#dropUpload paste->marksmith#pasteUpload",
105
+ **data_attributes
106
+ },
107
+ disabled:,
108
+ placeholder:,
109
+ autofocus:,
110
+ style:
111
+ %>
112
+ <%= content_tag :div, class: "ms:hidden ms:markdown-preview", id: "markdown-preview-#{name}", data: { marksmith_target: "previewElement" } do %>
113
+ <div class="button-spinner">
114
+ <div class="double-bounce1"></div>
115
+ <div class="double-bounce2"></div>
116
+ </div>
117
+ <% end %>
118
+ </div>
119
+ </div>
120
+ <% end %>
@@ -0,0 +1,3 @@
1
+ <%= content_tag :div, class: "ms:prose ms:prose-zinc" do %>
2
+ <%= sanitize(@body, tags: %w(table th tr td span) + ActionView::Helpers::SanitizeHelper.sanitizer_vendor.safe_list_sanitizer.allowed_tags.to_a) %>
3
+ <% end %>
@@ -0,0 +1,33 @@
1
+ # Files in the config/locales directory are used for internationalization and
2
+ # are automatically loaded by Rails. If you want to use locales other than
3
+ # English, add the necessary files in this directory.
4
+ #
5
+ # To use the locales, use `I18n.t`:
6
+ #
7
+ # I18n.t "hello"
8
+ #
9
+ # In views, this is aliased to just `t`:
10
+ #
11
+ # <%= t("hello") %>
12
+ #
13
+ # To use a different locale, set it with `I18n.locale`:
14
+ #
15
+ # I18n.locale = :es
16
+ #
17
+ # This would use the information in config/locales/es.yml.
18
+ #
19
+ # To learn more about the API, please read the Rails Internationalization guide
20
+ # at https://guides.rubyonrails.org/i18n.html.
21
+ #
22
+ # Be aware that YAML interprets the following case-insensitive strings as
23
+ # booleans: `true`, `false`, `on`, `off`, `yes`, `no`. Therefore, these strings
24
+ # must be quoted to be interpreted as strings. For example:
25
+ #
26
+ # en:
27
+ # "yes": yup
28
+ # enabled: "ON"
29
+ # TODO: add keys here
30
+
31
+ en:
32
+ marksmith:
33
+ hello: "Hello world"
data/config/routes.rb ADDED
@@ -0,0 +1,3 @@
1
+ Marksmith::Engine.routes.draw do
2
+ resources :markdown_previews, only: [:create]
3
+ end
data/config/vite.json ADDED
@@ -0,0 +1,16 @@
1
+ {
2
+ "all": {
3
+ "sourceCodeDir": "app/frontend",
4
+ "watchAdditionalPaths": []
5
+ },
6
+ "development": {
7
+ "autoBuild": true,
8
+ "publicOutputDir": "vite-dev",
9
+ "port": 3036
10
+ },
11
+ "test": {
12
+ "autoBuild": true,
13
+ "publicOutputDir": "vite-test",
14
+ "port": 3037
15
+ }
16
+ }
@@ -0,0 +1,25 @@
1
+ module Marksmith
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace Marksmith
4
+
5
+ initializer "marksmith.view_helpers" do
6
+ ActiveSupport.on_load :action_view do
7
+ ActionView::Base.include Marksmith::Helper
8
+
9
+ module FormBuilderExtensions
10
+ def marksmith(*args, **kwargs, &block)
11
+ @template.marksmith_tag(*args, **kwargs.merge(form: self), &block)
12
+ end
13
+ end
14
+
15
+ ActionView::Helpers::FormBuilder.include FormBuilderExtensions
16
+ end
17
+ end
18
+
19
+ initializer "marksmith.assets.precompile" do |app|
20
+ if Rails.application.config.respond_to?(:assets)
21
+ app.config.assets.precompile << "marksmith_manifest.js"
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,3 @@
1
+ module Marksmith
2
+ VERSION = "0.0.4"
3
+ end
data/lib/marksmith.rb ADDED
@@ -0,0 +1,5 @@
1
+ require "marksmith/version"
2
+ require "marksmith/engine"
3
+
4
+ module Marksmith
5
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :marksmith do
3
+ # # Task goes here
4
+ # end
metadata ADDED
@@ -0,0 +1,131 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: marksmith
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.4
5
+ platform: ruby
6
+ authors:
7
+ - Adrian Marin
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2025-01-22 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 7.0.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 7.0.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: redcarpet
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rouge
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: Marksmith is a GitHub-style markdown editor for Ruby on Rails applications.
56
+ email:
57
+ - adrian@adrianthedev.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - MIT-LICENSE
63
+ - README.md
64
+ - Rakefile
65
+ - app/assets/config/marksmith_manifest.js
66
+ - app/assets/images/marksmith/svgs/bold.svg
67
+ - app/assets/images/marksmith/svgs/code.svg
68
+ - app/assets/images/marksmith/svgs/color-swatch copy.svg
69
+ - app/assets/images/marksmith/svgs/color-swatch.svg
70
+ - app/assets/images/marksmith/svgs/heading.svg
71
+ - app/assets/images/marksmith/svgs/italic.svg
72
+ - app/assets/images/marksmith/svgs/link copy.svg
73
+ - app/assets/images/marksmith/svgs/link.svg
74
+ - app/assets/images/marksmith/svgs/list-bullet.svg
75
+ - app/assets/images/marksmith/svgs/list-todo.svg
76
+ - app/assets/images/marksmith/svgs/numbered-list.svg
77
+ - app/assets/images/marksmith/svgs/photo.svg
78
+ - app/assets/images/marksmith/svgs/quote.svg
79
+ - app/assets/stylesheets/marksmith.css
80
+ - app/assets/stylesheets/marksmith/application.css
81
+ - app/controllers/marksmith/application_controller.rb
82
+ - app/controllers/marksmith/markdown_previews_controller.rb
83
+ - app/frontend/entrypoints/application.css
84
+ - app/frontend/entrypoints/application.js
85
+ - app/frontend/entrypoints/javascript/controllers/application.js
86
+ - app/frontend/entrypoints/javascript/controllers/index.js
87
+ - app/frontend/entrypoints/javascript/controllers/marksmith_controller.js
88
+ - app/helpers/marksmith/application_helper.rb
89
+ - app/helpers/marksmith/helper.rb
90
+ - app/jobs/marksmith/application_job.rb
91
+ - app/mailers/marksmith/application_mailer.rb
92
+ - app/models/marksmith/application_record.rb
93
+ - app/models/marksmith/renderer.rb
94
+ - app/views/layouts/marksmith/application.html.erb
95
+ - app/views/marksmith/markdown_previews/create.turbo_stream.erb
96
+ - app/views/marksmith/shared/_editor.html.erb
97
+ - app/views/marksmith/shared/_rendered_body.html.erb
98
+ - config/locales/marksmith.en.yml
99
+ - config/routes.rb
100
+ - config/vite.json
101
+ - lib/marksmith.rb
102
+ - lib/marksmith/engine.rb
103
+ - lib/marksmith/version.rb
104
+ - lib/tasks/marksmith_tasks.rake
105
+ homepage: https://github.com/avo-hq/marksmith
106
+ licenses:
107
+ - MIT
108
+ metadata:
109
+ homepage_uri: https://github.com/avo-hq/marksmith
110
+ source_code_uri: https://github.com/avo-hq/marksmith
111
+ changelog_uri: https://github.com/avo-hq/marksmith/releases
112
+ post_install_message:
113
+ rdoc_options: []
114
+ require_paths:
115
+ - lib
116
+ required_ruby_version: !ruby/object:Gem::Requirement
117
+ requirements:
118
+ - - ">="
119
+ - !ruby/object:Gem::Version
120
+ version: '0'
121
+ required_rubygems_version: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - ">="
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ requirements: []
127
+ rubygems_version: 3.4.10
128
+ signing_key:
129
+ specification_version: 4
130
+ summary: Marksmith is a GitHub-style markdown editor for Ruby on Rails applications.
131
+ test_files: []