action_markdown 0.1.0

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 293af657a085cc950228d941a8d449c8c335a83043843bd4733a3b69cd6422c8
4
+ data.tar.gz: 5e6e747ee48734dac51e1a06f61078d84ea4da676dae6df53182d783c32a4920
5
+ SHA512:
6
+ metadata.gz: 9ba60286b520a138d923f3a7634ef70fececd6d67d543f8ee4d818879a0cd99b4dc12ed0b7969b2989a74c639770a3774074377f69ae913cf8e25dc490c0a01e
7
+ data.tar.gz: 77406fd0f6231c75475dafbe9978980144ea7c7fab76d09b37ef491dfe1a51e73dc0d54cfc387af4a12b9de27b58ea056d30f7ce5c5cf9f3395af482581deefc
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2022 Alexandre Ruban
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,68 @@
1
+ # Welcome to ActionMarkdown
2
+
3
+ Do you like GitHub issues Markdown editor? I love it too! ActionMarkdown aims to provide the same feature out of the box for Rails applications. With ActionMarkdown, it is easy to write some Markdown text in a form field and convert it to HTML seamlessly in the view.
4
+
5
+ ## Installation
6
+
7
+ Let's add this line to our application's `Gemfile`:
8
+
9
+ ```ruby
10
+ gem "action_markdown"
11
+ ```
12
+
13
+ We can then run the installation script to copy the migration file:
14
+
15
+ ```bash
16
+ bin/rails action_markdown:install
17
+ ```
18
+
19
+ Last but not least, we need to run the migration:
20
+
21
+ ```bash
22
+ bin/rails db:migrate
23
+ ```
24
+
25
+ ActionMarkdown is now installed, we are good to go!
26
+
27
+ ## Usage
28
+
29
+ Let's imagine we want to write articles in the Markdown format. In our Rails application, we will have an `Article`. To add Markdown content, we need to use the `has_markdown` macro like this:
30
+
31
+ ```rb
32
+ class Article < ApplicationRecord
33
+ has_markdown :content
34
+
35
+ validates :content, presence: true
36
+ end
37
+ ```
38
+
39
+ Without adding any new migration, we can now create a new article with Markdown text:
40
+
41
+ ```rb
42
+ markdown = <<~MARKDOWN
43
+ # Title
44
+
45
+ This is a paragraph.
46
+ MARKDOWN
47
+
48
+ article = Article.create! content: markdown
49
+ ```
50
+
51
+ In the view, the Markdown content will be converted to HTML. For example, in the `ArticlesController#show` view, we can render the content converted to HTML like this:
52
+
53
+ ```erb
54
+ <%# articles/show.html.erb %>
55
+
56
+ <%= @article.content %>
57
+ ```
58
+
59
+ In the view above, the Markdown content will automatically be converted to the following HTML:
60
+
61
+ ```html
62
+ <h1>Title</h1>
63
+ <p>This is a paragraph.</p>
64
+ ```
65
+
66
+ ## License
67
+
68
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -0,0 +1,5 @@
1
+ module ActionMarkdown
2
+ class ApplicationRecord < ActiveRecord::Base
3
+ self.abstract_class = true
4
+ end
5
+ end
@@ -0,0 +1,11 @@
1
+ module ActionMarkdown
2
+ class MarkdownText < ApplicationRecord
3
+ self.table_name = "action_markdown_markdown_texts"
4
+
5
+ serialize :body, ActionMarkdown::Content
6
+
7
+ belongs_to :record, polymorphic: true, touch: true
8
+
9
+ delegate :to_s, :to_html, to: :body
10
+ end
11
+ end
@@ -0,0 +1 @@
1
+ <%= sanitize content.to_html %>
@@ -0,0 +1,26 @@
1
+ class CreateActionMarkdownTables < ActiveRecord::Migration[7.0]
2
+ def change
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_markdown_markdown_texts, id: primary_key_type do |t|
7
+ t.string :name, null: false
8
+ t.text :body, size: :long
9
+ t.references :record, null: false, polymorphic: true, index: false, type: foreign_key_type
10
+
11
+ t.timestamps
12
+
13
+ t.index %i[record_type record_id name], name: "index_action_markdown_markdown_texts_uniqueness", unique: true
14
+ end
15
+ end
16
+
17
+ private
18
+
19
+ def primary_and_foreign_key_types
20
+ config = Rails.configuration.generators
21
+ setting = config.options[config.orm][:primary_key_type]
22
+ primary_key_type = setting || :primary_key
23
+ foreign_key_type = setting || :bigint
24
+ [primary_key_type, foreign_key_type]
25
+ end
26
+ end
@@ -0,0 +1,20 @@
1
+ module ActionMarkdown
2
+ module Attribute
3
+ def has_markdown(name)
4
+ class_eval <<-CODE, __FILE__, __LINE__ + 1
5
+ def #{name}
6
+ markdown_#{name} || build_markdown_#{name}
7
+ end
8
+
9
+ def #{name}=(body)
10
+ self.#{name}.body = body
11
+ end
12
+ CODE
13
+
14
+ has_one :"markdown_#{name}", -> { where(name: name) }, class_name: "ActionMarkdown::MarkdownText",
15
+ as: :record, inverse_of: :record, autosave: true, dependent: :destroy
16
+
17
+ scope :"with_markdown_#{name}", -> { includes("markdown_#{name}") }
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,33 @@
1
+ module ActionMarkdown
2
+ class Content
3
+ include ActiveModel::Conversion, Rendering, Serialization
4
+
5
+ def initialize(body)
6
+ @body = body
7
+ end
8
+
9
+ def to_html
10
+ markdown_renderer.render(body)
11
+ end
12
+
13
+ def to_s
14
+ render partial: to_partial_path, layout: false, locals: { content: self }
15
+ end
16
+
17
+ private
18
+
19
+ attr_accessor :body
20
+
21
+ def markdown_renderer
22
+ @markdown_renderer ||= Redcarpet::Markdown.new(
23
+ Renderer,
24
+ no_intra_emphasis: true,
25
+ fenced_code_blocks: true,
26
+ autolink: true,
27
+ strikethrough: true,
28
+ superscript: true,
29
+ tables: true
30
+ )
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,11 @@
1
+ module ActionMarkdown
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace ActionMarkdown
4
+
5
+ initializer "action_markdown.attribute" do
6
+ ActiveSupport.on_load(:active_record) do
7
+ extend ActionMarkdown::Attribute
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,7 @@
1
+ require "rouge/plugins/redcarpet"
2
+
3
+ module ActionMarkdown
4
+ class Renderer < Redcarpet::Render::HTML
5
+ include Rouge::Plugins::Redcarpet
6
+ end
7
+ end
@@ -0,0 +1,13 @@
1
+ module ActionMarkdown
2
+ module Rendering
3
+ private
4
+
5
+ def render(*args, &block)
6
+ action_controller_renderer.render(*args, &block)
7
+ end
8
+
9
+ def action_controller_renderer
10
+ ActionController::Base.renderer
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActionMarkdown
4
+ module Serialization
5
+ extend ActiveSupport::Concern
6
+
7
+ class_methods do
8
+ def load(content)
9
+ new(content) if content
10
+ end
11
+
12
+ def dump(content)
13
+ case content
14
+ when nil
15
+ nil
16
+ when self
17
+ content.to_html
18
+ when ActionMarkdown::MarkdownText
19
+ content.body.to_html
20
+ else
21
+ new(content).to_html
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,3 @@
1
+ module ActionMarkdown
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,14 @@
1
+ require "action_markdown/version"
2
+ require "action_markdown/engine"
3
+
4
+ require "redcarpet"
5
+
6
+ module ActionMarkdown
7
+ extend ActiveSupport::Autoload
8
+
9
+ autoload :Attribute
10
+ autoload :Content
11
+ autoload :Renderer
12
+ autoload :Rendering
13
+ autoload :Serialization
14
+ end
@@ -0,0 +1,9 @@
1
+ module ActionMarkdown
2
+ module Generators
3
+ class InstallGenerator < ::Rails::Generators::Base
4
+ def create_migrations
5
+ rails_command "railties:install:migrations FROM=action_markdown", inline: true
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ desc "Copy over the migration"
4
+ task "action_markdown:install" do
5
+ Rails::Command.invoke :generate, ["action_markdown:install"]
6
+ end
metadata ADDED
@@ -0,0 +1,101 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: action_markdown
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Alexandre Ruban
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2022-11-27 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: rouge
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: redcarpet
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:
56
+ email:
57
+ - alexandre@hey.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - MIT-LICENSE
63
+ - README.md
64
+ - app/models/action_markdown/application_record.rb
65
+ - app/models/action_markdown/markdown_text.rb
66
+ - app/views/action_markdown/contents/_content.html.erb
67
+ - db/migrate/20221110163240_create_action_markdown_tables.rb
68
+ - lib/action_markdown.rb
69
+ - lib/action_markdown/attribute.rb
70
+ - lib/action_markdown/content.rb
71
+ - lib/action_markdown/engine.rb
72
+ - lib/action_markdown/renderer.rb
73
+ - lib/action_markdown/rendering.rb
74
+ - lib/action_markdown/serialization.rb
75
+ - lib/action_markdown/version.rb
76
+ - lib/generators/action_markdown/install/install_generator.rb
77
+ - lib/tasks/action_markdown_tasks.rake
78
+ homepage: https://github.com/alexandreruban/action-markdown
79
+ licenses:
80
+ - MIT
81
+ metadata: {}
82
+ post_install_message:
83
+ rdoc_options: []
84
+ require_paths:
85
+ - lib
86
+ required_ruby_version: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ required_rubygems_version: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ requirements: []
97
+ rubygems_version: 3.3.7
98
+ signing_key:
99
+ specification_version: 4
100
+ summary: Add rich text to your Ruby on Rails application thanks to Markdown.
101
+ test_files: []