action_markdown 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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: []