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