tiptap-ruby 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: 2347235752700026d263aa5a0616d89f99014c42da52edbf92c30374eb2cfded
4
+ data.tar.gz: d97eefd5023412988280b6edf6741186f310452ab657a02c62419296de680334
5
+ SHA512:
6
+ metadata.gz: 79f61b79665a0a0d48cc69322c50b24d05a3b330c6f2a6dd8242f31dc628d8f9e1d69db06024b7bb642290c44a001df13379fcc45872a6c0f0f3e28df0bc4a3f
7
+ data.tar.gz: 4b5ab21878bccf69ccdc8dfdc3fe04bbc5e3a91a65140b6d2b1759bce3ed13a6169fb47d2697415cd5d27261fa27c11f1d40c2e0387a1f0e30cf38fc296244a0
data/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ ## [Unreleased]
2
+
3
+ ## [0.1.0] - 2023-10-28
4
+
5
+ - Initial release
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2023 Chad Wilken
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,89 @@
1
+ # Tiptap
2
+
3
+ A gem for parsing, generating, and rendering TipTap Documents and Nodes using Ruby.
4
+
5
+ ## Installation
6
+
7
+ Install the gem and add to the application's Gemfile by executing:
8
+
9
+ $ bundle add tiptap-ruby
10
+
11
+ If bundler is not being used to manage dependencies, install the gem by executing:
12
+
13
+ $ gem install tiptap-ruby
14
+
15
+ ## Usage
16
+
17
+ ### Parsing a TipTap Document
18
+
19
+ You can parse a TipTap Document so that you can interact with it to do things such as add content (Nodes) or render it as HTML, JSON, or plain text:
20
+
21
+ ```ruby
22
+ document = TipTap::Document.from_json(tiptap_json)
23
+ ```
24
+
25
+ ### Generate a New Document
26
+
27
+ ```ruby
28
+ document = TipTap::Document.new
29
+ ```
30
+
31
+ You can also pass a block and the new Document will be yielded to the block.
32
+
33
+ ```ruby
34
+ TipTap::Document.new do |document|
35
+ # Do something with document
36
+ end
37
+ ```
38
+
39
+ ### Add Content to the Document
40
+
41
+ Now that you have a Document you can add content to it.
42
+
43
+ ```ruby
44
+ document.heading(level: 1) do |heading|
45
+ heading.text("My Import Document", marks: [{type: "italic"}])
46
+ end
47
+ ```
48
+
49
+ Until the gem implements all of the node types and the documentation is complete, refer to the `Document` class to see the nodes that can be appended.
50
+
51
+ ### Generate Output
52
+
53
+ Once you have a Document with some content you can render it to HTML, JSON, and plain text.
54
+
55
+ #### JSON
56
+
57
+ ```ruby
58
+ document.to_json # => { type: 'doc', content: […nodes]}
59
+ ```
60
+
61
+ ### HTML
62
+
63
+ ```ruby
64
+ document.to_html # => <div class="tiptap-document"><h1><em>My Important Document</em></h1></div>
65
+ ```
66
+
67
+ ### Plain Text
68
+
69
+ Rendering to plain text is useful if you want to search the contents of your TipTap content.
70
+
71
+ ```ruby
72
+ document.to_plain_text # => My Important Document
73
+ ```
74
+
75
+ ## Development
76
+
77
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `bundle exec rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
78
+
79
+ To install this gem onto your local machine, run `bundle install`.
80
+
81
+ To release a new version, update the version number in `version.rb`, and then run `bin/release` or `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
82
+
83
+ ## Contributing
84
+
85
+ Bug reports and pull requests are welcome on GitHub at https://github.com/chadwilken/tiptap-ruby.
86
+
87
+ ## License
88
+
89
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "tip_tap/html_renderable"
4
+ require "tip_tap/json_renderable"
5
+ require "tip_tap/plain_text_renderable"
6
+ require "tip_tap/has_content"
7
+
8
+ # This is the class that all child nodes will be added to.
9
+ # This is the root object for TipTap.
10
+ module TipTap
11
+ class Document
12
+ include JsonRenderable
13
+ include HtmlRenderable
14
+ include PlainTextRenderable
15
+ include HasContent
16
+
17
+ self.type_name = "doc"
18
+ self.html_tag = :div
19
+ self.html_class_name = "tiptap-document"
20
+
21
+ def heading(level: 1, &block)
22
+ raise ArgumentError, "Block required" if block.nil?
23
+
24
+ add_content(Nodes::Heading.new(level: level, &block))
25
+ end
26
+
27
+ def paragraph(&block)
28
+ add_content(Nodes::Paragraph.new(&block))
29
+ end
30
+
31
+ def task_list(&block)
32
+ raise ArgumentError, "Block required" if block.nil?
33
+
34
+ add_content(Nodes::TaskList.new(&block))
35
+ end
36
+
37
+ def bullet_list(&block)
38
+ raise ArgumentError, "Block required" if block.nil?
39
+
40
+ add_content(Nodes::BulletList.new(&block))
41
+ end
42
+
43
+ def image(src:)
44
+ add_content(Nodes::Image.new(src: src))
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/hash"
4
+
5
+ module TipTap
6
+ module HasContent
7
+ attr_reader :attrs, :content
8
+
9
+ def self.included(base)
10
+ base.extend(ClassMethods)
11
+ end
12
+
13
+ # Create a new document or node, optionally passing in attributes (attrs) and nodes
14
+ # @param nodes [Array] An array of nodes to add to this node
15
+ # @param attributes [Hash] A hash of attributes to add to this node e.g. { 'level' => 1 }
16
+ def initialize(content = [], **attributes)
17
+ # This will convert the attrs key to camelcase for example :image_id is converted into 'imageId'
18
+ @attrs = Hash(attributes).deep_transform_keys { |key| key.to_s.camelcase(:lower) }
19
+ @content = content
20
+ yield self if block_given?
21
+ end
22
+
23
+ def find_node(node_type)
24
+ content.find { |child| child.is_a?(node_type) }
25
+ end
26
+
27
+ def add_content(node)
28
+ @content << node
29
+ end
30
+
31
+ module ClassMethods
32
+ # Create a new instance from a TipTap JSON object.
33
+ # All nodes are recursively parsed and converted to Ruby objects
34
+ # All nodes must be registered in the registry.
35
+ # @param json [Hash] The JSON object to parse
36
+ def from_json(json)
37
+ return new if json.nil?
38
+
39
+ json.deep_stringify_keys!
40
+
41
+ content = Array(json["content"]).map do |node|
42
+ TipTap.node_for(node["type"]).from_json(node)
43
+ end
44
+
45
+ new(content, **Hash(json["attrs"]))
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "action_view"
4
+
5
+ module TipTap
6
+ module HtmlRenderable
7
+ include ActionView::Helpers::TextHelper
8
+ include ActionView::Helpers::AssetTagHelper
9
+
10
+ # ActionView::Helpers::TagHelper requires output_buffer accessor
11
+ # This is included by ActionView::Helpers::TextHelper
12
+ attr_accessor :output_buffer
13
+
14
+ def self.included(base)
15
+ base.extend(ClassMethods)
16
+ end
17
+
18
+ module ClassMethods
19
+ def html_tag=(name_or_proc)
20
+ @html_tag = name_or_proc
21
+ end
22
+
23
+ def html_tag
24
+ @html_tag
25
+ end
26
+
27
+ def html_class_name=(name_or_proc)
28
+ @html_class_name = name_or_proc
29
+ end
30
+
31
+ def html_class_name
32
+ @html_class_name
33
+ end
34
+ end
35
+
36
+ def html_tag
37
+ tag = self.class.html_tag
38
+ case tag
39
+ when Proc
40
+ instance_eval(&tag)
41
+ else
42
+ tag
43
+ end
44
+ end
45
+
46
+ def html_class_name
47
+ classes = self.class.html_class_name
48
+ case classes
49
+ when Proc
50
+ instance_eval(&classes)
51
+ else
52
+ classes
53
+ end
54
+ end
55
+
56
+ def to_html
57
+ content_tag(html_tag, safe_join(content.map(&:to_html)), class: html_class_name)
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "tip_tap/registry"
4
+
5
+ module TipTap
6
+ module JsonRenderable
7
+ def self.included(base)
8
+ base.extend(ClassMethods)
9
+ end
10
+
11
+ module ClassMethods
12
+ def type_name=(type_name)
13
+ @type_name = type_name
14
+ Registry.register(type_name, self)
15
+ end
16
+
17
+ def type_name
18
+ @type_name
19
+ end
20
+ end
21
+
22
+ def type_name
23
+ self.class.type_name
24
+ end
25
+
26
+ def include_empty_content_in_json?
27
+ true
28
+ end
29
+
30
+ # Generate a JSON object that is useable by the editor
31
+ def to_json
32
+ json = {type: type_name}
33
+ json = json.merge(content: content.map(&:to_json)) if should_include_content?
34
+ json = json.merge(attrs: attrs.deep_symbolize_keys) if attrs.present?
35
+ json
36
+ end
37
+
38
+ private
39
+
40
+ def should_include_content?
41
+ content.present? || (content.empty? && include_empty_content_in_json?)
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "tip_tap/html_renderable"
4
+ require "tip_tap/json_renderable"
5
+ require "tip_tap/plain_text_renderable"
6
+ require "tip_tap/has_content"
7
+
8
+ # This is the base class for all TipTap nodes.
9
+ # It provides some basic functionality that all nodes need such as
10
+ # converting to HTML, JSON, and plain text
11
+ module TipTap
12
+ class Node
13
+ include HtmlRenderable
14
+ include JsonRenderable
15
+ include PlainTextRenderable
16
+ include HasContent
17
+ end
18
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "tip_tap/node"
4
+
5
+ module TipTap
6
+ module Nodes
7
+ class BulletList < Node
8
+ self.type_name = "bulletList"
9
+ self.html_tag = :ul
10
+ self.html_class_name = "bullet-list"
11
+
12
+ def list_item(&block)
13
+ raise ArgumentError, "Block required" if block.nil?
14
+
15
+ add_content(ListItem.new(&block))
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "tip_tap/node"
4
+
5
+ module TipTap
6
+ module Nodes
7
+ class HardBreak < Node
8
+ self.type_name = "hardBreak"
9
+
10
+ def include_empty_content_in_json?
11
+ false
12
+ end
13
+
14
+ def to_html
15
+ tag.br
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "tip_tap/node"
4
+
5
+ module TipTap
6
+ module Nodes
7
+ class Heading < Node
8
+ self.type_name = "heading"
9
+ self.html_tag = proc { "h#{level}" }
10
+
11
+ def text(text, marks: [])
12
+ add_content(Text.new(text, marks: marks))
13
+ end
14
+
15
+ def level
16
+ attrs["level"]
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "tip_tap/node"
4
+
5
+ module TipTap
6
+ module Nodes
7
+ class HorizontalRule < Node
8
+ self.type_name = "horizontalRule"
9
+
10
+ def include_empty_content_in_json?
11
+ false
12
+ end
13
+
14
+ def to_html
15
+ tag.hr
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "tip_tap/node"
4
+
5
+ module TipTap
6
+ module Nodes
7
+ class Image < Node
8
+ self.type_name = "image"
9
+
10
+ def include_empty_content_in_json?
11
+ false
12
+ end
13
+
14
+ def to_html
15
+ image_tag(src)
16
+ end
17
+
18
+ def src
19
+ attrs["src"]
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "tip_tap/node"
4
+
5
+ module TipTap
6
+ module Nodes
7
+ class ListItem < Node
8
+ self.type_name = "listItem"
9
+ self.html_tag = :li
10
+ self.html_class_name = "list-item"
11
+
12
+ def paragraph(&block)
13
+ raise ArgumentError, "Block required" if block.nil?
14
+
15
+ add_content(Paragraph.new(&block))
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "tip_tap/node"
4
+
5
+ module TipTap
6
+ module Nodes
7
+ class OrderedList < Node
8
+ self.type_name = "orderedList"
9
+ self.html_tag = :ol
10
+ self.html_class_name = "ordered-list"
11
+
12
+ def list_item(&block)
13
+ raise ArgumentError, "Block required" if block.nil?
14
+
15
+ add_content(ListItem.new(&block))
16
+ end
17
+
18
+ def start
19
+ attrs["start"]
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "tip_tap/node"
4
+
5
+ module TipTap
6
+ module Nodes
7
+ class Paragraph < Node
8
+ self.type_name = "paragraph"
9
+ self.html_tag = :p
10
+
11
+ def text(text, marks: [])
12
+ add_content(Text.new(text, marks: marks))
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "tip_tap/node"
4
+
5
+ module TipTap
6
+ module Nodes
7
+ class TaskItem < Node
8
+ self.type_name = "taskItem"
9
+ self.html_tag = :li
10
+ self.html_class_name = proc { class_names("task-item", {checked: checked?}) }
11
+
12
+ def paragraph(&block)
13
+ raise ArgumentError, "Block required" if block.nil?
14
+
15
+ add_content(Paragraph.new(&block))
16
+ end
17
+
18
+ def checked?
19
+ attrs["checked"]
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "tip_tap/node"
4
+
5
+ module TipTap
6
+ module Nodes
7
+ class TaskList < Node
8
+ self.type_name = "taskList"
9
+ self.html_tag = :ul
10
+ self.html_class_name = "task-list"
11
+
12
+ def task_item(checked: false, &block)
13
+ raise ArgumentError, "Block required" if block.nil?
14
+
15
+ add_content(TaskItem.new(checked: checked, &block))
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "tip_tap/json_renderable"
4
+ require "tip_tap/html_renderable"
5
+
6
+ module TipTap
7
+ module Nodes
8
+ class Text
9
+ include JsonRenderable
10
+ include HtmlRenderable
11
+
12
+ attr_reader :text, :marks
13
+
14
+ self.type_name = "text"
15
+
16
+ def initialize(text, marks: [])
17
+ @text = text
18
+ @marks = marks.map(&:deep_stringify_keys)
19
+ end
20
+
21
+ def self.from_json(json)
22
+ json.deep_stringify_keys!
23
+
24
+ new(json["text"], marks: Array(json["marks"]))
25
+ end
26
+
27
+ def to_json
28
+ {type: type_name, text: text, marks: marks.map(&:deep_symbolize_keys)}.compact_blank
29
+ end
30
+
31
+ def to_html
32
+ value = text
33
+ value = content_tag(:u, value) if underline?
34
+ value = content_tag(:em, value) if italic?
35
+ value = content_tag(:strong, value) if bold?
36
+ value = content_tag(:a, value, href: link_href, target: link_target) if link?
37
+ value
38
+ end
39
+
40
+ def to_plain_text
41
+ text
42
+ end
43
+
44
+ def italic?
45
+ has_mark_with_type?("italic")
46
+ end
47
+
48
+ def bold?
49
+ has_mark_with_type?("bold")
50
+ end
51
+
52
+ def underline?
53
+ has_mark_with_type?("underline")
54
+ end
55
+
56
+ def link?
57
+ has_mark_with_type?("link")
58
+ end
59
+
60
+ def link_href
61
+ marks.find { |mark| mark["type"] == "link" }&.dig("attrs", "href")
62
+ end
63
+
64
+ def link_target
65
+ marks.find { |mark| mark["type"] == "link" }&.dig("attrs", "target")
66
+ end
67
+
68
+ private
69
+
70
+ def has_mark_with_type?(type)
71
+ marks.any? { |mark| mark["type"] == type }
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TipTap
4
+ module PlainTextRenderable
5
+ # Useful for searching
6
+ def to_plain_text
7
+ content.map(&:to_plain_text).join(" ")
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This is the registry for all the nodes that TipTap knows about.
4
+ # It's a simple hash that maps TipTap JS node names to Ruby classes.
5
+ # Registering a new node is as simple as:
6
+ # TipTap::Registry.register('myNode', MyNode)
7
+ module TipTap
8
+ class Registry
9
+ MissingNodeError = Class.new(StandardError)
10
+
11
+ def self.register(name, klass)
12
+ registry[name.to_s] = klass
13
+ end
14
+
15
+ def self.node_for(name)
16
+ registry.fetch(name.to_s) { raise MissingNodeError.new("Unknown node type: #{name}") }
17
+ end
18
+
19
+ def self.clear
20
+ @registry = {}
21
+ end
22
+
23
+ def self.registry
24
+ @registry ||= {}
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TipTap
4
+ VERSION = "0.1.0"
5
+ end
data/lib/tip_tap.rb ADDED
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "tip_tap/version"
4
+ require "tip_tap/registry"
5
+ require "tip_tap/document"
6
+ require "tip_tap/nodes/bullet_list"
7
+ require "tip_tap/nodes/hard_break"
8
+ require "tip_tap/nodes/heading"
9
+ require "tip_tap/nodes/horizontal_rule"
10
+ require "tip_tap/nodes/list_item"
11
+ require "tip_tap/nodes/ordered_list"
12
+ require "tip_tap/nodes/paragraph"
13
+ require "tip_tap/nodes/task_item"
14
+ require "tip_tap/nodes/task_list"
15
+ require "tip_tap/nodes/text"
16
+ require "tip_tap/nodes/image"
17
+
18
+ module TipTap
19
+ class Error < StandardError; end
20
+
21
+ def self.node_for(name)
22
+ Registry.node_for(name)
23
+ end
24
+ end
data/lib/tiptap.rb ADDED
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "tip_tap"
metadata ADDED
@@ -0,0 +1,99 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tiptap-ruby
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Chad Wilken
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-10-28 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: actionview
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '6.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '6.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: activesupport
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '6.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '6.0'
41
+ description: A gem for parsing, generating, and rendering TipTap Documents and Nodes
42
+ using Ruby.
43
+ email:
44
+ - chad.wilken@gmail.com
45
+ executables: []
46
+ extensions: []
47
+ extra_rdoc_files: []
48
+ files:
49
+ - CHANGELOG.md
50
+ - LICENSE.txt
51
+ - README.md
52
+ - lib/tip_tap.rb
53
+ - lib/tip_tap/document.rb
54
+ - lib/tip_tap/has_content.rb
55
+ - lib/tip_tap/html_renderable.rb
56
+ - lib/tip_tap/json_renderable.rb
57
+ - lib/tip_tap/node.rb
58
+ - lib/tip_tap/nodes/bullet_list.rb
59
+ - lib/tip_tap/nodes/hard_break.rb
60
+ - lib/tip_tap/nodes/heading.rb
61
+ - lib/tip_tap/nodes/horizontal_rule.rb
62
+ - lib/tip_tap/nodes/image.rb
63
+ - lib/tip_tap/nodes/list_item.rb
64
+ - lib/tip_tap/nodes/ordered_list.rb
65
+ - lib/tip_tap/nodes/paragraph.rb
66
+ - lib/tip_tap/nodes/task_item.rb
67
+ - lib/tip_tap/nodes/task_list.rb
68
+ - lib/tip_tap/nodes/text.rb
69
+ - lib/tip_tap/plain_text_renderable.rb
70
+ - lib/tip_tap/registry.rb
71
+ - lib/tip_tap/version.rb
72
+ - lib/tiptap.rb
73
+ homepage: https://github.com/chadwilken/tiptap-ruby
74
+ licenses:
75
+ - MIT
76
+ metadata:
77
+ homepage_uri: https://github.com/chadwilken/tiptap-ruby
78
+ source_code_uri: https://github.com/chadwilken/tiptap-ruby
79
+ changelog_uri: https://github.com/chadwilken/tiptap-ruby/blob/master/CHANGELOG.md
80
+ post_install_message:
81
+ rdoc_options: []
82
+ require_paths:
83
+ - lib
84
+ required_ruby_version: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: 2.7.0
89
+ required_rubygems_version: !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ requirements: []
95
+ rubygems_version: 3.4.6
96
+ signing_key:
97
+ specification_version: 4
98
+ summary: Parse, generate and render TipTap documents in Ruby.
99
+ test_files: []