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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +12 -0
- data/LICENSE +21 -0
- data/README.md +78 -0
- data/bin/article_json_export_google_doc.rb +22 -0
- data/bin/article_json_export_html.rb +14 -0
- data/bin/article_json_parse_google_doc.rb +14 -0
- data/bin/update_reference_document.sh +18 -0
- data/lib/article_json/article.rb +53 -0
- data/lib/article_json/configuration.rb +24 -0
- data/lib/article_json/elements/base.rb +40 -0
- data/lib/article_json/elements/embed.rb +58 -0
- data/lib/article_json/elements/heading.rb +37 -0
- data/lib/article_json/elements/image.rb +41 -0
- data/lib/article_json/elements/list.rb +37 -0
- data/lib/article_json/elements/paragraph.rb +31 -0
- data/lib/article_json/elements/quote.rb +41 -0
- data/lib/article_json/elements/text.rb +45 -0
- data/lib/article_json/elements/text_box.rb +37 -0
- data/lib/article_json/export/html/elements/base.rb +59 -0
- data/lib/article_json/export/html/elements/embed.rb +28 -0
- data/lib/article_json/export/html/elements/heading.rb +19 -0
- data/lib/article_json/export/html/elements/image.rb +33 -0
- data/lib/article_json/export/html/elements/list.rb +25 -0
- data/lib/article_json/export/html/elements/paragraph.rb +17 -0
- data/lib/article_json/export/html/elements/quote.rb +29 -0
- data/lib/article_json/export/html/elements/shared/caption.rb +22 -0
- data/lib/article_json/export/html/elements/shared/float.rb +17 -0
- data/lib/article_json/export/html/elements/text.rb +44 -0
- data/lib/article_json/export/html/elements/text_box.rb +25 -0
- data/lib/article_json/export/html/exporter.rb +22 -0
- data/lib/article_json/import/google_doc/html/css_analyzer.rb +144 -0
- data/lib/article_json/import/google_doc/html/embedded_facebook_video_parser.rb +33 -0
- data/lib/article_json/import/google_doc/html/embedded_parser.rb +113 -0
- data/lib/article_json/import/google_doc/html/embedded_slideshare_parser.rb +36 -0
- data/lib/article_json/import/google_doc/html/embedded_tweet_parser.rb +37 -0
- data/lib/article_json/import/google_doc/html/embedded_vimeo_video_parser.rb +29 -0
- data/lib/article_json/import/google_doc/html/embedded_youtube_video_parser.rb +33 -0
- data/lib/article_json/import/google_doc/html/heading_parser.rb +38 -0
- data/lib/article_json/import/google_doc/html/image_parser.rb +75 -0
- data/lib/article_json/import/google_doc/html/list_parser.rb +46 -0
- data/lib/article_json/import/google_doc/html/node_analyzer.rb +111 -0
- data/lib/article_json/import/google_doc/html/paragraph_parser.rb +26 -0
- data/lib/article_json/import/google_doc/html/parser.rb +125 -0
- data/lib/article_json/import/google_doc/html/quote_parser.rb +46 -0
- data/lib/article_json/import/google_doc/html/shared/caption.rb +20 -0
- data/lib/article_json/import/google_doc/html/shared/float.rb +21 -0
- data/lib/article_json/import/google_doc/html/text_box_parser.rb +49 -0
- data/lib/article_json/import/google_doc/html/text_parser.rb +89 -0
- data/lib/article_json/utils/o_embed_resolver/base.rb +63 -0
- data/lib/article_json/utils/o_embed_resolver/facebook_video.rb +21 -0
- data/lib/article_json/utils/o_embed_resolver/slideshare.rb +22 -0
- data/lib/article_json/utils/o_embed_resolver/tweet.rb +23 -0
- data/lib/article_json/utils/o_embed_resolver/vimeo_video.rb +21 -0
- data/lib/article_json/utils/o_embed_resolver/youtube_video.rb +21 -0
- data/lib/article_json/utils.rb +11 -0
- data/lib/article_json/version.rb +3 -0
- data/lib/article_json.rb +55 -0
- 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
|
+
[](https://badge.fury.io/rb/article_json)
|
6
|
+
[](https://travis-ci.org/Devex/article_json)
|
7
|
+
[](https://codeclimate.com/github/Devex/article_json)
|
8
|
+
[](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
|
+
|