article_json 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +12 -0
  3. data/LICENSE +21 -0
  4. data/README.md +78 -0
  5. data/bin/article_json_export_google_doc.rb +22 -0
  6. data/bin/article_json_export_html.rb +14 -0
  7. data/bin/article_json_parse_google_doc.rb +14 -0
  8. data/bin/update_reference_document.sh +18 -0
  9. data/lib/article_json/article.rb +53 -0
  10. data/lib/article_json/configuration.rb +24 -0
  11. data/lib/article_json/elements/base.rb +40 -0
  12. data/lib/article_json/elements/embed.rb +58 -0
  13. data/lib/article_json/elements/heading.rb +37 -0
  14. data/lib/article_json/elements/image.rb +41 -0
  15. data/lib/article_json/elements/list.rb +37 -0
  16. data/lib/article_json/elements/paragraph.rb +31 -0
  17. data/lib/article_json/elements/quote.rb +41 -0
  18. data/lib/article_json/elements/text.rb +45 -0
  19. data/lib/article_json/elements/text_box.rb +37 -0
  20. data/lib/article_json/export/html/elements/base.rb +59 -0
  21. data/lib/article_json/export/html/elements/embed.rb +28 -0
  22. data/lib/article_json/export/html/elements/heading.rb +19 -0
  23. data/lib/article_json/export/html/elements/image.rb +33 -0
  24. data/lib/article_json/export/html/elements/list.rb +25 -0
  25. data/lib/article_json/export/html/elements/paragraph.rb +17 -0
  26. data/lib/article_json/export/html/elements/quote.rb +29 -0
  27. data/lib/article_json/export/html/elements/shared/caption.rb +22 -0
  28. data/lib/article_json/export/html/elements/shared/float.rb +17 -0
  29. data/lib/article_json/export/html/elements/text.rb +44 -0
  30. data/lib/article_json/export/html/elements/text_box.rb +25 -0
  31. data/lib/article_json/export/html/exporter.rb +22 -0
  32. data/lib/article_json/import/google_doc/html/css_analyzer.rb +144 -0
  33. data/lib/article_json/import/google_doc/html/embedded_facebook_video_parser.rb +33 -0
  34. data/lib/article_json/import/google_doc/html/embedded_parser.rb +113 -0
  35. data/lib/article_json/import/google_doc/html/embedded_slideshare_parser.rb +36 -0
  36. data/lib/article_json/import/google_doc/html/embedded_tweet_parser.rb +37 -0
  37. data/lib/article_json/import/google_doc/html/embedded_vimeo_video_parser.rb +29 -0
  38. data/lib/article_json/import/google_doc/html/embedded_youtube_video_parser.rb +33 -0
  39. data/lib/article_json/import/google_doc/html/heading_parser.rb +38 -0
  40. data/lib/article_json/import/google_doc/html/image_parser.rb +75 -0
  41. data/lib/article_json/import/google_doc/html/list_parser.rb +46 -0
  42. data/lib/article_json/import/google_doc/html/node_analyzer.rb +111 -0
  43. data/lib/article_json/import/google_doc/html/paragraph_parser.rb +26 -0
  44. data/lib/article_json/import/google_doc/html/parser.rb +125 -0
  45. data/lib/article_json/import/google_doc/html/quote_parser.rb +46 -0
  46. data/lib/article_json/import/google_doc/html/shared/caption.rb +20 -0
  47. data/lib/article_json/import/google_doc/html/shared/float.rb +21 -0
  48. data/lib/article_json/import/google_doc/html/text_box_parser.rb +49 -0
  49. data/lib/article_json/import/google_doc/html/text_parser.rb +89 -0
  50. data/lib/article_json/utils/o_embed_resolver/base.rb +63 -0
  51. data/lib/article_json/utils/o_embed_resolver/facebook_video.rb +21 -0
  52. data/lib/article_json/utils/o_embed_resolver/slideshare.rb +22 -0
  53. data/lib/article_json/utils/o_embed_resolver/tweet.rb +23 -0
  54. data/lib/article_json/utils/o_embed_resolver/vimeo_video.rb +21 -0
  55. data/lib/article_json/utils/o_embed_resolver/youtube_video.rb +21 -0
  56. data/lib/article_json/utils.rb +11 -0
  57. data/lib/article_json/version.rb +3 -0
  58. data/lib/article_json.rb +55 -0
  59. metadata +189 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 14715c8b4542d6737963ab39e16c97a2060454ab
4
+ data.tar.gz: ae62279949f41500e34cb18bd1642b73c6bbb86a
5
+ SHA512:
6
+ metadata.gz: 877ad153850744cd40a169240b1151ee09612775eb7bc4e53f5cebc60b0fc9c859e3861ebc4b1c3b119a618c905242945a681d1f749b1fedbfff69281ed5cd9c
7
+ data.tar.gz: a636ea3a56f54700275e31a38df2b41ed23f1c9d8199e5b5408b078c3e33fc999872406194bddc238bd57352a52f0e22c6ca3bef34ad43942b2a0eb06ed7d6f5
data/CHANGELOG.md ADDED
@@ -0,0 +1,12 @@
1
+ # Changelog
2
+
3
+ ## ? - WIP
4
+
5
+ ## 0.1.0 - 2017/09/20
6
+ This is the very first release, with the following functionality:
7
+ - article-json format that supports several basic elements; like headings,
8
+ paragraphs, images or lists
9
+ - Resolving of embedded elements like videos or tweets via OEmbed standard
10
+ - Conversion from and to JSON (or ruby hashes)
11
+ - Parsing of HTML exports from Google documents
12
+ - Export into plain HTML
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2017 Devex <https://www.devex.com>
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 all
13
+ 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 THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,78 @@
1
+ # article_json
2
+ JSON Format for News Articles & Ruby Gem.
3
+
4
+ ## Status
5
+ [![Gem Version](https://badge.fury.io/rb/article_json.svg)](https://badge.fury.io/rb/article_json)
6
+ [![Build Status](https://travis-ci.org/Devex/article_json.svg)](https://travis-ci.org/Devex/article_json)
7
+ [![Code Climate](https://codeclimate.com/github/Devex/article_json/badges/gpa.svg)](https://codeclimate.com/github/Devex/article_json)
8
+ [![Coverage Status](https://coveralls.io/repos/github/Devex/article_json/badge.svg?branch=master)](https://coveralls.io/github/Devex/article_json?branch=master)
9
+
10
+ ## Usage
11
+ First, install the gem with `gem install article_json` or add it to your Gemfile
12
+ via `gem 'article_json'`.
13
+
14
+ ### Ruby
15
+ ```ruby
16
+ require 'article_json'
17
+
18
+ # parse the HTML export of a Google Document
19
+ article = ArticleJSON::Article.from_google_doc_html(google_doc_html)
20
+
21
+ # initialize article-json format from storage (JSON string)
22
+ article = ArticleJSON::Article.from_json(json_string)
23
+
24
+ # initialize article-json format from storage (already parsed JSON)
25
+ article = ArticleJSON::Article.from_hash(parsed_json)
26
+
27
+ # export article as HTML
28
+ puts article.to_html
29
+
30
+ # export article as JSON
31
+ puts article.to_json
32
+ ```
33
+
34
+ ### CLI
35
+ To load, parse and html-export the latest version of the reference document,
36
+ run the following:
37
+
38
+ ```
39
+ $ export DOC_ID=1E4lncZE2jDkbE34eDyYQmXKA9O26BHUiwguz4S9qyE8
40
+ $ ./bin/article_json_export_google_doc.rb $DOC_ID \
41
+ | ./bin/article_json_parse_google_doc.rb \
42
+ | ./bin/article_json_export_html.rb
43
+ ```
44
+
45
+ ## Format
46
+ A full example of the format can be found in the test fixtures:
47
+ [Parsed Reference Document](https://github.com/Devex/article_json/blob/master/spec/fixtures/reference_document_parsed.json)
48
+
49
+ ## Import
50
+ ### Google Document Parser
51
+ This [Reference Document](https://docs.google.com/document/d/1E4lncZE2jDkbE34eDyYQmXKA9O26BHUiwguz4S9qyE8/edit?usp=sharing)
52
+ lists contains all supported formatting along with some descriptions.
53
+
54
+ ## Export
55
+ ### HTML
56
+ The HTML exporter generates a HTML string for a list of elements. An example of
57
+ the HTML export for the parsed reference document can be found
58
+ [here](https://github.com/Devex/article_json/blob/master/spec/fixtures/reference_document_exported.html).
59
+
60
+ ## Contributing
61
+ - Fork this repository
62
+ - Implement your feature or fix including Tests
63
+ - Update the [change log](CHANGELOG.md)
64
+ - Commit your changes with a meaningful commit message
65
+ - Create a pull request
66
+
67
+ Thank you!
68
+
69
+ See the
70
+ [list of contributors](https://github.com/Devex/article_json/contributors).
71
+
72
+ ### Tests
73
+ For the whole test suite, run `bundle exec rspec`.
74
+
75
+ For individual tests, run `bundle exec rspec spec/article_json/version_spec.rb`.
76
+
77
+ ## License
78
+ MIT License, see the [license file](LICENSE).
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
4
+ #
5
+ # Simple script to load an HTML export for a Google document by ID.
6
+ #
7
+ # Usage:
8
+ #
9
+ # ./bin/article_json_export_google_doc.rb $GOOGLE_DOC_ID
10
+ #
11
+ # Note: The document has to be publicly accessible via link. If the docuement is
12
+ # private, you can use the URL schema below and open it in a browser while
13
+ # being signed in to Google Drive.
14
+ #
15
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
16
+
17
+ require 'net/http'
18
+ require 'uri'
19
+
20
+ doc_id = ARGV.first
21
+ url = "https://docs.google.com/feeds/download/documents/export/Export?id=#{doc_id}&exportFormat=html"
22
+ puts Net::HTTP.get(URI.parse(url))
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
4
+ #
5
+ # Simple script to read a JSON document and export it to HTML.
6
+ #
7
+ # Usage:
8
+ #
9
+ # ./bin/article_json_export_html.rb < my_document.json
10
+ #
11
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
12
+
13
+ require_relative '../lib/article_json'
14
+ puts ArticleJSON::Article.from_json(ARGF.read).to_html
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
4
+ #
5
+ # Simple script to read a Google Doc HTML export from STDIN and parse it.
6
+ #
7
+ # Usage:
8
+ #
9
+ # ./bin/article_json_parse_google_doc.rb < my_document.html
10
+ #
11
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
12
+
13
+ require_relative '../lib/article_json'
14
+ puts ArticleJSON::Article.from_google_doc_html((ARGF.read)).to_json
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env sh
2
+
3
+ # set google doc id
4
+ DOC_ID="1E4lncZE2jDkbE34eDyYQmXKA9O26BHUiwguz4S9qyE8"
5
+
6
+ # set file locations
7
+ SOURCE_HTML_FILE="spec/fixtures/reference_document.html"
8
+ JSON_FILE="spec/fixtures/reference_document_parsed.json"
9
+ HTML_EXPORT_FILE="spec/fixtures/reference_document_exported.html"
10
+
11
+ # export the google doc to HTML
12
+ ./bin/article_json_export_google_doc.rb ${DOC_ID} > ${SOURCE_HTML_FILE}
13
+
14
+ # convert the google doc html export to JSON
15
+ ./bin/article_json_parse_google_doc.rb < ${SOURCE_HTML_FILE} | jq . > ${JSON_FILE}
16
+
17
+ # convert the JSON export to HTML
18
+ ./bin/article_json_export_html.rb < ${JSON_FILE} > ${HTML_EXPORT_FILE}
@@ -0,0 +1,53 @@
1
+ module ArticleJSON
2
+ class Article
3
+ attr_reader :elements
4
+
5
+ # @param [Arra[ArticleJSON::Elements::Base]] elements
6
+ def initialize(elements)
7
+ @elements = elements
8
+ end
9
+
10
+ # Hash representation of the article
11
+ # @return [Hash]
12
+ def to_h
13
+ {
14
+ article_json_version: VERSION,
15
+ content: @elements.map(&:to_h),
16
+ }
17
+ end
18
+
19
+ # JSON representation of the article
20
+ # @return [String]
21
+ def to_json
22
+ to_h.to_json
23
+ end
24
+
25
+ # HTML export of the article
26
+ # @return [String]
27
+ def to_html
28
+ ArticleJSON::Export::HTML::Exporter.new(@elements).html
29
+ end
30
+
31
+ class << self
32
+ # Build a new article from hash (like the one generated by #to_h)
33
+ # @return [ArticleJSON::Article]
34
+ def from_hash(hash)
35
+ hash = { content: hash } if hash.is_a?(Array)
36
+ new(ArticleJSON::Elements::Base.parse_hash_list(hash[:content]))
37
+ end
38
+
39
+ # Build a new article from JSON (like the one generated by #to_json)
40
+ # @return [ArticleJSON::Article]
41
+ def from_json(json)
42
+ from_hash(JSON.parse(json, symbolize_names: true))
43
+ end
44
+
45
+ # Build a new article from a Google Doc HTML export
46
+ # @return [ArticleJSON::Article]
47
+ def from_google_doc_html(html)
48
+ parser = ArticleJSON::Import::GoogleDoc::HTML::Parser.new(html)
49
+ new(parser.parsed_content)
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,24 @@
1
+ module ArticleJSON
2
+ ## Add configuration access and block to main module
3
+ class << self
4
+ attr_accessor :configuration
5
+
6
+ # @return [ArticleJSON::Configuration]
7
+ def configuration
8
+ @configuration ||= Configuration.new
9
+ end
10
+
11
+ def configure
12
+ yield(configuration)
13
+ end
14
+ end
15
+
16
+ class Configuration
17
+ attr_accessor :oembed_user_agent
18
+
19
+ def initialize
20
+ @oembed_user_agent = nil
21
+ end
22
+ end
23
+ end
24
+
@@ -0,0 +1,40 @@
1
+ module ArticleJSON
2
+ module Elements
3
+ class Base
4
+ attr_reader :type
5
+
6
+ class << self
7
+ # Create an element from a hash, based on the :type field
8
+ # @param [Hash] hash
9
+ # @return [ArticleJSON::Elements::Base]
10
+ def parse_hash(hash)
11
+ klass = element_classes[hash[:type].to_sym]
12
+ klass.parse_hash(hash) unless klass.nil?
13
+ end
14
+
15
+ # Create a list of elements from an array of hashes
16
+ # @param [Array[Hash]] hash_list
17
+ # @return [Array[ArticleJSON::Elements::Base]]
18
+ def parse_hash_list(hash_list)
19
+ hash_list.map { |hash| Base.parse_hash(hash) }.compact
20
+ end
21
+
22
+ private
23
+
24
+ def element_classes
25
+ {
26
+ embed: Embed,
27
+ heading: Heading,
28
+ image: Image,
29
+ list: List,
30
+ paragraph: Paragraph,
31
+ quote: Quote,
32
+ text: Text,
33
+ text_box: TextBox,
34
+ }
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+
@@ -0,0 +1,58 @@
1
+ module ArticleJSON
2
+ module Elements
3
+ class Embed < Base
4
+ attr_reader :embed_type, :embed_id, :caption, :tags
5
+
6
+ # @param [Symbol] embed_type
7
+ # @param [String] embed_id
8
+ # @param [Array[ArticleJSON::Elements::Text]] caption
9
+ # @param [Array] tags
10
+ def initialize(embed_type:, embed_id:, caption:, tags: [])
11
+ @type = :embed
12
+ @embed_type = embed_type
13
+ @embed_id = embed_id
14
+ @caption = caption
15
+ @tags = tags
16
+ end
17
+
18
+ # Hash representation of this embedded element
19
+ # @return [Hash]
20
+ def to_h
21
+ {
22
+ type: type,
23
+ embed_type: embed_type,
24
+ embed_id: embed_id,
25
+ tags: tags,
26
+ caption: caption.map(&:to_h),
27
+ }
28
+ end
29
+
30
+ # Obtain the oembed data for this embed element
31
+ # @return [Hash]
32
+ def oembed_data
33
+ oembed_resolver&.oembed_data
34
+ end
35
+
36
+ private
37
+
38
+ # @return [ArticleJSON::Utils::OEmbedResolver::Base]
39
+ def oembed_resolver
40
+ @oembed_resolver ||=
41
+ ArticleJSON::Utils::OEmbedResolver::Base.build(self)
42
+ end
43
+
44
+ class << self
45
+ # Create an embedded element from Hash
46
+ # @return [ArticleJSON::Elements::Embed]
47
+ def parse_hash(hash)
48
+ new(
49
+ embed_type: hash[:embed_type],
50
+ embed_id: hash[:embed_id],
51
+ caption: parse_hash_list(hash[:caption]),
52
+ tags: hash[:tags]
53
+ )
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,37 @@
1
+ module ArticleJSON
2
+ module Elements
3
+ class Heading < Base
4
+ attr_reader :level, :content
5
+
6
+ # @param [String] level
7
+ # @param [String] content
8
+ def initialize(level:, content:)
9
+ @level = level
10
+ @content = content
11
+ @type = :heading
12
+ end
13
+
14
+ # Hash representation of this heading element
15
+ # @return [Hash]
16
+ def to_h
17
+ {
18
+ type: type,
19
+ level: level,
20
+ content: content,
21
+ }
22
+ end
23
+
24
+ class << self
25
+ # Create a heading element from Hash
26
+ # @return [ArticleJSON::Elements::Heading]
27
+ def parse_hash(hash)
28
+ new(
29
+ level: hash[:level].to_i,
30
+ content: hash[:content]
31
+ )
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+
@@ -0,0 +1,41 @@
1
+ module ArticleJSON
2
+ module Elements
3
+ class Image < Base
4
+ attr_reader :source_url, :caption, :float
5
+
6
+ # @param [String] source_url
7
+ # @param [Array[ArticleJSON::Elements::Text]] caption
8
+ # @param [Symbol] float
9
+ def initialize(source_url:, caption:, float: nil)
10
+ @type = :image
11
+ @source_url = source_url
12
+ @caption = caption
13
+ @float = float
14
+ end
15
+
16
+ # Hash representation of this image element
17
+ # @return [Hash]
18
+ def to_h
19
+ {
20
+ type: type,
21
+ source_url: source_url,
22
+ float: float,
23
+ caption: caption.map(&:to_h),
24
+ }
25
+ end
26
+
27
+ class << self
28
+ # Create a image element from Hash
29
+ # @return [ArticleJSON::Elements::Image]
30
+ def parse_hash(hash)
31
+ new(
32
+ source_url: hash[:source_url],
33
+ caption: parse_hash_list(hash[:caption]),
34
+ float: hash[:float]&.to_sym
35
+ )
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+
@@ -0,0 +1,37 @@
1
+ module ArticleJSON
2
+ module Elements
3
+ class List < Base
4
+ attr_reader :content, :list_type
5
+
6
+ # @param [Array[ArticleJSON::Elements::Paragraph]] content
7
+ # @param [Symbol] list_type
8
+ def initialize(content:, list_type: :unordered)
9
+ @type = :list
10
+ @content = content
11
+ @list_type = list_type
12
+ end
13
+
14
+ # Hash representation of this heading element
15
+ # @return [Hash]
16
+ def to_h
17
+ {
18
+ type: type,
19
+ list_type: list_type,
20
+ content: content.map(&:to_h),
21
+ }
22
+ end
23
+
24
+ class << self
25
+ # Create a list element from Hash
26
+ # @return [ArticleJSON::Elements::List]
27
+ def parse_hash(hash)
28
+ new(
29
+ content: parse_hash_list(hash[:content]),
30
+ list_type: hash[:list_type].to_sym
31
+ )
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+
@@ -0,0 +1,31 @@
1
+ module ArticleJSON
2
+ module Elements
3
+ class Paragraph < Base
4
+ attr_reader :content
5
+
6
+ # @param [Array[ArticleJSON::Elements::Text]] content
7
+ def initialize(content:)
8
+ @type = :paragraph
9
+ @content = content
10
+ end
11
+
12
+ # Hash representation of this heading element
13
+ # @return [Hash]
14
+ def to_h
15
+ {
16
+ type: type,
17
+ content: content.map(&:to_h),
18
+ }
19
+ end
20
+
21
+ class << self
22
+ # Create a paragraph element from Hash
23
+ # @return [ArticleJSON::Elements::Paragraph]
24
+ def parse_hash(hash)
25
+ new(content: parse_hash_list(hash[:content]))
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+
@@ -0,0 +1,41 @@
1
+ module ArticleJSON
2
+ module Elements
3
+ class Quote < Base
4
+ attr_reader :content, :caption, :float
5
+
6
+ # @param [Array[ArticleJSON::Elements::Paragraph]] content
7
+ # @param [Array[ArticleJSON::Elements::Text]] caption
8
+ # @param [Symbol] float
9
+ def initialize(content:, caption:, float: nil)
10
+ @type = :quote
11
+ @content = content
12
+ @caption = caption
13
+ @float = float
14
+ end
15
+
16
+ # Hash representation of this quote element
17
+ # @return [Hash]
18
+ def to_h
19
+ {
20
+ type: type,
21
+ float: float,
22
+ content: content.map(&:to_h),
23
+ caption: caption.map(&:to_h),
24
+ }
25
+ end
26
+
27
+ class << self
28
+ # Create a quote element from Hash
29
+ # @return [ArticleJSON::Elements::Quote]
30
+ def parse_hash(hash)
31
+ new(
32
+ content: parse_hash_list(hash[:content]),
33
+ caption: parse_hash_list(hash[:caption]),
34
+ float: hash[:float]&.to_sym
35
+ )
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+
@@ -0,0 +1,45 @@
1
+ module ArticleJSON
2
+ module Elements
3
+ class Text < Base
4
+ attr_reader :content, :bold, :italic, :href
5
+
6
+ # @param [String] content
7
+ # @param [Boolean] bold
8
+ # @param [Boolean] italic
9
+ # @param [String] href
10
+ def initialize(content:, bold: false, italic: false, href: nil)
11
+ @type = :text
12
+ @content = content
13
+ @bold = bold
14
+ @italic = italic
15
+ @href = href
16
+ end
17
+
18
+ # Hash representation of this text node
19
+ # @return [Hash]
20
+ def to_h
21
+ {
22
+ type: type,
23
+ content: content,
24
+ bold: bold,
25
+ italic: italic,
26
+ href: href,
27
+ }
28
+ end
29
+
30
+ class << self
31
+ # Create a text element from Hash
32
+ # @return [ArticleJSON::Elements::Text]
33
+ def parse_hash(hash)
34
+ new(
35
+ content: hash[:content],
36
+ bold: hash[:bold],
37
+ italic: hash[:italic],
38
+ href: hash[:href]
39
+ )
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+
@@ -0,0 +1,37 @@
1
+ module ArticleJSON
2
+ module Elements
3
+ class TextBox < Base
4
+ attr_reader :content, :float
5
+
6
+ # @param [Array[Paragraph|Heading|List]] content
7
+ # @param [Symbol] float
8
+ def initialize(content:, float: nil)
9
+ @type = :text_box
10
+ @content = content
11
+ @float = float
12
+ end
13
+
14
+ # Hash representation of this text box element
15
+ # @return [Hash]
16
+ def to_h
17
+ {
18
+ type: type,
19
+ float: float,
20
+ content: content.map(&:to_h),
21
+ }
22
+ end
23
+
24
+ class << self
25
+ # Create a text box element from Hash
26
+ # @return [ArticleJSON::Elements::TextBox]
27
+ def parse_hash(hash)
28
+ new(
29
+ content: parse_hash_list(hash[:content]),
30
+ float: hash[:float]&.to_sym
31
+ )
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+