article_json 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.
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
+