article_json 0.3.8 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +24 -0
- data/README.md +108 -72
- data/bin/article_json_export_amp.rb +1 -0
- data/bin/article_json_export_apple_news.rb +15 -0
- data/bin/article_json_export_facebook.rb +1 -0
- data/bin/article_json_export_html.rb +1 -0
- data/bin/article_json_export_plain_text.rb +1 -0
- data/bin/article_json_parse_google_doc.rb +1 -0
- data/bin/check_google_doc_export.rb +41 -0
- data/bin/update_oembed_request-stubs.sh +1 -3
- data/bin/update_reference_document.sh +4 -0
- data/lib/article_json/article.rb +22 -2
- data/lib/article_json/configuration.rb +2 -1
- data/lib/article_json/elements/base.rb +0 -1
- data/lib/article_json/export/amp/elements/embed.rb +1 -1
- data/lib/article_json/export/apple_news/elements/base.rb +53 -0
- data/lib/article_json/export/apple_news/elements/embed.rb +130 -0
- data/lib/article_json/export/apple_news/elements/heading.rb +32 -0
- data/lib/article_json/export/apple_news/elements/image.rb +58 -0
- data/lib/article_json/export/apple_news/elements/list.rb +67 -0
- data/lib/article_json/export/apple_news/elements/paragraph.rb +36 -0
- data/lib/article_json/export/apple_news/elements/quote.rb +60 -0
- data/lib/article_json/export/apple_news/elements/text.rb +42 -0
- data/lib/article_json/export/apple_news/elements/text_box.rb +51 -0
- data/lib/article_json/export/apple_news/exporter.rb +37 -0
- data/lib/article_json/import/google_doc/html/image_parser.rb +16 -2
- data/lib/article_json/import/google_doc/html/node_analyzer.rb +11 -1
- data/lib/article_json/import/google_doc/html/parser.rb +6 -1
- data/lib/article_json/utils/o_embed_resolver/facebook_video.rb +17 -1
- data/lib/article_json/utils/o_embed_resolver/youtube_video.rb +1 -1
- data/lib/article_json/version.rb +1 -1
- data/lib/article_json.rb +11 -0
- metadata +33 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 561ba1f1fff25cba3e32eea10bdff57757ab6776a688bc78f85ec4eafeb62b32
|
4
|
+
data.tar.gz: e72e2425f7008d24be098be9024a27f493c2f13c99577ec71d7dda953564bcef
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 14e75d7a01ad409337b79b98075063807de0d18dd911980c7ef816668ddf4adc6f02211fb36ed54a530962bf0839628b217cfd6c849ff6153575c9e9274500b2
|
7
|
+
data.tar.gz: a2a1eac1de2d0d8b0379c1d1bbc85a7af99e33c44ebdc544d88de7983597be878e59c9bc90a2a1a4958b4dcb1ea26d4bc5817fb6944e04e02224d1af8fd52353
|
data/CHANGELOG.md
CHANGED
@@ -1,4 +1,28 @@
|
|
1
1
|
# Changelog
|
2
|
+
## 0.4.0 - 2024/01/17
|
3
|
+
In this fourth release we **added support for Apple News**:
|
4
|
+
**New**:
|
5
|
+
Support for Apple News Format, specifically the following elements:
|
6
|
+
- text
|
7
|
+
- text boxes
|
8
|
+
- lists
|
9
|
+
- pull quotes
|
10
|
+
- image
|
11
|
+
- embed objects (posts from X etc.)
|
12
|
+
- image captions for images and embed objects
|
13
|
+
- video
|
14
|
+
Support for Ruby 3.2
|
15
|
+
|
16
|
+
**Removes**:
|
17
|
+
Support for Ruby 2.3
|
18
|
+
|
19
|
+
**Refactoring**:
|
20
|
+
- Rubocop autocorrections
|
21
|
+
|
22
|
+
**Fix:**
|
23
|
+
- Fix failing rspec tests
|
24
|
+
|
25
|
+
|
2
26
|
## 0.3.8 - 2020/7/31
|
3
27
|
- **Improvements:**
|
4
28
|
- Add a script to update oembed stubs fixtures.
|
data/README.md
CHANGED
@@ -1,10 +1,25 @@
|
|
1
1
|
# article_json
|
2
|
-
|
2
|
+
The `article_json` gem is a Ruby library designed to simplify the conversion and manipulation of structured articles in various formats, allowing easy importing, manipulation and export of content across different platforms and environments.
|
3
|
+
|
4
|
+
It takes an article from a Google Doc and creates a JSON version of it.
|
5
|
+
|
6
|
+
From there it can export the article:
|
7
|
+
- as HTML
|
8
|
+
- as AMP
|
9
|
+
- as Apple News Format (ANF)
|
10
|
+
- as Facebook Instant Article HTML
|
11
|
+
- as plain text
|
12
|
+
- as JSON
|
13
|
+
|
14
|
+
It also provides functionalities to parse content from Google Document HTML exports and initialize articles from JSON strings or already parsed JSON.
|
15
|
+
|
16
|
+
---
|
3
17
|
|
4
18
|
## Status
|
5
19
|
[![Gem Version](https://badge.fury.io/rb/article_json.svg)](https://badge.fury.io/rb/article_json)
|
6
|
-
[![
|
7
|
-
[![
|
20
|
+
[![Check Google Doc](https://github.com/Devex/article_json/workflows/Check%20Google%20Doc/badge.svg)](https://github.com/Devex/article_json/actions/workflows/check-google-doc.yml)
|
21
|
+
[![RSpec](https://github.com/Devex/article_json/workflows/rspec/badge.svg)](https://github.com/Devex/article_json/actions/workflows/rspec.yml)
|
22
|
+
[![Code Climate](https://codeclimate.com/github/Devex/article_json/badges/gpa.svg)](https://codeclimate.com/github/Devex/article_json?event=push)
|
8
23
|
[![Coverage Status](https://coveralls.io/repos/github/Devex/article_json/badge.svg?branch=master)](https://coveralls.io/github/Devex/article_json?branch=master)
|
9
24
|
|
10
25
|
## Usage
|
@@ -32,6 +47,9 @@ puts article.to_amp
|
|
32
47
|
# get javascript libraries needed for the AMP article
|
33
48
|
puts article.amp_exporter.amp_libraries
|
34
49
|
|
50
|
+
# export article as Apple News Format (ANF)
|
51
|
+
puts article.to_apple_news
|
52
|
+
|
35
53
|
# export article as Facebook Instant Article HTML
|
36
54
|
puts article.to_facebook_instant_article
|
37
55
|
|
@@ -43,35 +61,47 @@ puts article.to_json
|
|
43
61
|
```
|
44
62
|
|
45
63
|
### CLI
|
46
|
-
To load, parse and
|
47
|
-
run the following:
|
64
|
+
To load, parse and export the latest (amp/ apple news/ facebook/ html) version of the reference document, run the following:
|
48
65
|
|
49
|
-
```
|
66
|
+
```bash
|
50
67
|
$ export DOC_ID=1E4lncZE2jDkbE34eDyYQmXKA9O26BHUiwguz4S9qyE8
|
51
68
|
$ ./bin/article_json_export_google_doc.rb $DOC_ID \
|
52
69
|
| ./bin/article_json_parse_google_doc.rb \
|
53
70
|
| ./bin/article_json_export_html.rb
|
71
|
+
## OR
|
72
|
+
# | ./bin/article_json_export_amp.rb
|
73
|
+
# | ./bin/article_json_export_apple_news.rb
|
74
|
+
# | ./bin/article_json_export_facebook.rb
|
75
|
+
# | ./bin/article_json_export_plain_text.rb
|
76
|
+
```
|
77
|
+
|
78
|
+
Alternatively, you can concatenate your command line commands, like so:
|
79
|
+
```bash
|
80
|
+
$ ./bin/article_json_export_google_doc.rb $DOC_ID > test_ref_doc.html
|
81
|
+
$ cat test_ref_doc.html | bin/article_json_parse_google_doc.rb > \
|
82
|
+
test_ref_doc_parsed_apple.json
|
83
|
+
$ cat test_ref_doc_parsed_apple.json | bin/article_json_export_apple_news.rb > \
|
84
|
+
test_ref_doc_exported_apple.json
|
54
85
|
```
|
55
86
|
|
56
|
-
You can also update
|
57
|
-
document (html, json, amp, facebook instant article and plain txt) by
|
58
|
-
running the following command:
|
87
|
+
You can also update _all_ the different exported versions of the reference document _(amp, apple_news, facebook, google_doc, html and plain_text)_ by running the following command:
|
59
88
|
|
60
89
|
```
|
61
90
|
$ ./bin/update_reference_document.sh
|
62
91
|
```
|
63
92
|
|
64
|
-
When running the tests, we use some fixtures to mock the responses for oembed
|
65
|
-
|
93
|
+
When running the tests, we use some fixtures to mock the responses for oembed requests, but these may change over time.
|
94
|
+
|
95
|
+
To update them, run:
|
66
96
|
|
67
97
|
```
|
68
98
|
$ ./bin/update_oembed_request-stubs.sh
|
69
99
|
```
|
70
100
|
|
71
101
|
### Configuration
|
72
|
-
|
73
|
-
|
74
|
-
available setting:
|
102
|
+
Some configuration options allow a more tailored usage of the `article_json` gem.
|
103
|
+
|
104
|
+
The following code snippet gives an example for every available setting:
|
75
105
|
|
76
106
|
```ruby
|
77
107
|
ArticleJSON.configure do |config|
|
@@ -84,48 +114,63 @@ ArticleJSON.configure do |config|
|
|
84
114
|
:html,
|
85
115
|
advertisement: ArticleJSON::Export::HTML::Elements::Advertisement
|
86
116
|
)
|
87
|
-
|
117
|
+
|
88
118
|
# You can also overwrite existing exporters:
|
89
119
|
config.register_element_exporters(
|
90
120
|
:html,
|
91
121
|
image: ArticleJSON::Export::HTML::Elements::ScaledImage
|
92
122
|
)
|
93
|
-
|
123
|
+
|
94
124
|
# And you can define multiple custom exporters:
|
95
125
|
config.register_element_exporters(
|
96
126
|
:html,
|
97
127
|
advertisement: ArticleJSON::Export::HTML::Elements::Advertisement,
|
98
128
|
image: ArticleJSON::Export::HTML::Elements::ScaledImage
|
99
129
|
)
|
100
|
-
|
101
|
-
# It works the same way for custom AMP, FacebookInstantArticle, or
|
102
|
-
#
|
130
|
+
|
131
|
+
# It works the same way for custom AMP, FacebookInstantArticle, or PlainText
|
132
|
+
# exporters:
|
103
133
|
config.register_element_exporters(
|
104
134
|
:amp, # Or change this for `:facebook_instant_article` or `:plain_text`
|
105
135
|
image: ArticleJSON::Export::AMP::Elements::ScaledImage
|
106
|
-
)
|
136
|
+
)
|
107
137
|
end
|
108
|
-
```
|
138
|
+
```
|
139
|
+
|
140
|
+
### Facebook Oembed
|
141
|
+
Facebook deprecated its public endpoints for embeddable Facebook content in 2020 (See https://developers.facebook.com/docs/plugins/oembed-legacy for more info).
|
142
|
+
|
143
|
+
You now need to use a Facebook token to access the new oembed endpoints. You can configure the gem to use this token so:
|
144
|
+
|
145
|
+
``` ruby
|
146
|
+
ArticleJSON.configure do |config|
|
147
|
+
# 'token' being the combination of the app-id and the access token joined
|
148
|
+
# with the pipe symbol (`|`)
|
149
|
+
config.facebook_token = 'token'
|
150
|
+
end
|
151
|
+
```
|
152
|
+
|
153
|
+
Find more info about the access token [here](https://developers.facebook.com/docs/plugins/oembed#access-tokens).
|
109
154
|
|
110
155
|
## Format
|
111
|
-
A full example of the format can be found in the test fixtures
|
112
|
-
[Parsed Reference Document](https://github.com/Devex/article_json/blob/master/spec/fixtures/reference_document_parsed.json)
|
156
|
+
A [full example of the format](https://github.com/Devex/article_json/blob/master/spec/fixtures/reference_document_parsed.json) can be found in the test fixtures.
|
113
157
|
|
114
158
|
## Import
|
115
159
|
### Google Document Parser
|
116
|
-
This [
|
117
|
-
lists contains all supported formatting along with some descriptions.
|
160
|
+
This [reference document](https://docs.google.com/document/d/1E4lncZE2jDkbE34eDyYQmXKA9O26BHUiwguz4S9qyE8/editusp=sharing) contains all the supported formatting along with some descriptions.
|
118
161
|
|
119
162
|
## Add custom elements
|
120
|
-
Sometimes you might want to place additional elements into the article, like e.g. advertisements.
|
121
|
-
|
122
|
-
Each element that is added this way will directly get placed in between paragraphs of the article.
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
You can pass any type of element into this method.
|
128
|
-
|
163
|
+
Sometimes you might want to place additional elements into the article, like e.g. advertisements. `article_json` supports this via `article.place_additional_elements`, which accepts an array of elements that you can define in your code.
|
164
|
+
|
165
|
+
Each element that is added this way will directly get placed in between paragraphs of the article. The method ensures that an additional element is never added before or after any node other than paragraphs (e.g. an image). The elements are added in the order you pass them into the method.
|
166
|
+
|
167
|
+
If the article does not have enough space to place all the provided elements, they will be placed after the last
|
168
|
+
element in the article.
|
169
|
+
|
170
|
+
You can pass any type of element into this method.
|
171
|
+
|
172
|
+
If the objects you pass in are instances of elements defined within this gem (e.g. `ArticleJSON::Elements::Image`), you won't have to do anything else to render them.
|
173
|
+
|
129
174
|
If you pass in an instance of a custom class (e.g. `MyAdvertisement`), make sure to register an exporter for this type (check the _Configuration_ section for more details).
|
130
175
|
|
131
176
|
Example using only existing elements:
|
@@ -134,45 +179,45 @@ Example using only existing elements:
|
|
134
179
|
article = ArticleJSON::Article.from_hash(parsed_json)
|
135
180
|
|
136
181
|
# Within your code, create additional elements you would like to add
|
137
|
-
image_advertisement =
|
138
|
-
ArticleJSON::Elements::Image.new(source_url: 'https://robohash.org/great-ad',
|
182
|
+
image_advertisement =
|
183
|
+
ArticleJSON::Elements::Image.new(source_url: 'https://robohash.org/great-ad',
|
139
184
|
caption: ArticleJSON::Elements::Text.new(
|
140
185
|
content: 'Buy more robots!',
|
141
186
|
href: '/robot-sale'
|
142
187
|
))
|
143
|
-
text_box_similar_articles =
|
188
|
+
text_box_similar_articles =
|
144
189
|
ArticleJSON::Elements::TextBox.new(content: [
|
145
|
-
ArticleJSON::Elements::Heading.new(level: 3, content: 'Read more...'),
|
190
|
+
ArticleJSON::Elements::Heading.new(level: 3, content: 'Read more...'),
|
146
191
|
ArticleJSON::Elements::List.new(content: [
|
147
192
|
ArticleJSON::Elements::Paragraph(content: [
|
148
|
-
ArticleJSON::Elements::Text.new(content: 'Very similar article',
|
193
|
+
ArticleJSON::Elements::Text.new(content: 'Very similar article',
|
149
194
|
href: '/news/123'),
|
150
195
|
]),
|
151
196
|
ArticleJSON::Elements::Paragraph(content: [
|
152
|
-
ArticleJSON::Elements::Text.new(content: 'Great article!',
|
197
|
+
ArticleJSON::Elements::Text.new(content: 'Great article!',
|
153
198
|
href: '/news/42'),
|
154
199
|
]),
|
155
|
-
]),
|
200
|
+
]),
|
156
201
|
])
|
157
202
|
|
158
203
|
# Add these elements to the article
|
159
|
-
article.place_additional_elements([image_advertisement,
|
204
|
+
article.place_additional_elements([image_advertisement,
|
160
205
|
text_box_similar_articles])
|
161
|
-
|
162
|
-
# Export the article to the different formats as you would normally do
|
206
|
+
|
207
|
+
# Export the article to the different formats as you would normally do
|
163
208
|
article.to_html # this will now include the custom elements
|
164
|
-
```
|
209
|
+
```
|
165
210
|
|
166
211
|
Example with custom advertisement elements:
|
167
212
|
```ruby
|
168
213
|
# Define your custom element class
|
169
214
|
class MyAdvertisement
|
170
215
|
attr_reader :url
|
171
|
-
|
216
|
+
|
172
217
|
def initialize(url:)
|
173
218
|
@url = url
|
174
219
|
end
|
175
|
-
|
220
|
+
|
176
221
|
def type
|
177
222
|
:my_advertisement
|
178
223
|
end
|
@@ -180,9 +225,9 @@ end
|
|
180
225
|
|
181
226
|
# Define an exporter for your class, we only use HTML in this example but this
|
182
227
|
# would work similarly for AMP or other formats
|
183
|
-
class MyAdvertisementExporter <
|
184
|
-
ArticleJSON::Export::HTML::Elements::Base
|
185
|
-
|
228
|
+
class MyAdvertisementExporter <
|
229
|
+
ArticleJSON::Export::HTML::Elements::Base
|
230
|
+
|
186
231
|
# Needs to implement the `#export` method
|
187
232
|
def export
|
188
233
|
create_element(:iframe, src: @element.url)
|
@@ -209,35 +254,26 @@ article.to_html
|
|
209
254
|
|
210
255
|
## Export
|
211
256
|
### HTML
|
212
|
-
The HTML exporter generates
|
213
|
-
the HTML export for the parsed reference document can be found
|
214
|
-
[here](https://github.com/Devex/article_json/blob/master/spec/fixtures/reference_document_exported.html).
|
257
|
+
The HTML exporter generates an HTML string for a list of elements. An example of the HTML export for the parsed reference document can be found [here](https://github.com/Devex/article_json/blob/master/spec/fixtures/reference_document_exported.html).
|
215
258
|
|
216
259
|
### AMP
|
217
|
-
The AMP exporter generates an AMP HTML representation of the elements.
|
260
|
+
The AMP exporter generates an AMP HTML representation of the elements.
|
218
261
|
|
219
262
|
AMP uses [custom HTML tags](https://www.ampproject.org/docs/reference/components), some of which require additional Javascript libraries.
|
220
|
-
If you have an `article` (see code example in _Usage_ section), you can get a list of the custom tags required by this article by calling `article.amp_exporter.custom_element_tags` and by calling `article.amp_exporter.amp_libraries` you get a list of `<script>` tags that can directly be included on your page to render the AMP article.
|
221
263
|
|
222
|
-
|
223
|
-
|
224
|
-
[here](https://github.com/Devex/article_json/blob/master/spec/fixtures/reference_document_exported.amp.html).
|
264
|
+
If you have an `article` (see code example in _Usage_ section), you can get a list of the custom tags required by this article by calling `article.amp_exporter.custom_element_tags` and calling `article.amp_exporter.amp_libraries` gives a list of `<script>` tags that can directly be included on your page to render the AMP article.
|
265
|
+
|
266
|
+
An example of the AMP HTML export for the parsed reference document can be found [here](https://github.com/Devex/article_json/blob/master/spec/fixtures/reference_document_exported.amp.html).
|
225
267
|
|
226
268
|
### Facebook Instant Articles
|
227
|
-
The `FacebookInstantArticle` exporter generates a custom HTML string for a list
|
228
|
-
of elements. An example of the Facebook Instant Article export for the parsed
|
229
|
-
reference document can be found
|
230
|
-
[here](https://github.com/Devex/article_json/blob/master/spec/fixtures/reference_document_exported.html).
|
269
|
+
The `FacebookInstantArticle` exporter generates a custom HTML string for a list of elements. An example of the Facebook Instant Article export for the parsed reference document can be found [here](https://github.com/Devex/article_json/blob/master/spec/fixtures/reference_document_exported.html).
|
231
270
|
|
232
|
-
To learn more about the Facebook Instant Article HTML format see have a look at
|
233
|
-
the [Facebook Developer Documentation](https://developers.facebook.com/docs/instant-articles/guides/format-overview).
|
271
|
+
To learn more about the Facebook Instant Article HTML format see have a look at the [Facebook Developer Documentation](https://developers.facebook.com/docs/instant-articles/guides/format-overview).
|
234
272
|
|
235
273
|
### Plain Text
|
236
|
-
As the name suggests, this exporter generates a plain text version of the article.
|
237
|
-
Rich text elements like images, embeds or even text boxes are not being rendered.
|
274
|
+
As the name suggests, this exporter generates a plain text version of the article. Rich text elements like images, embeds or even text boxes are not being rendered.
|
238
275
|
|
239
|
-
The reference document rendered as plain text can be found
|
240
|
-
[here](https://github.com/Devex/article_json/blob/master/spec/fixtures/reference_document_exported.txt).
|
276
|
+
The reference document rendered as plain text can be found [here](https://github.com/Devex/article_json/blob/master/spec/fixtures/reference_document_exported.txt).
|
241
277
|
|
242
278
|
Usage:
|
243
279
|
```ruby
|
@@ -245,22 +281,22 @@ Usage:
|
|
245
281
|
article = ArticleJSON::Article.from_hash(parsed_json)
|
246
282
|
|
247
283
|
# Then simply call `#to_plain_text` on it
|
248
|
-
article.to_plain_text
|
284
|
+
article.to_plain_text
|
249
285
|
```
|
250
286
|
|
251
287
|
## Contributing
|
252
288
|
- Fork this repository
|
253
|
-
- Implement your feature or fix including
|
289
|
+
- Implement your feature or fix including tests
|
254
290
|
- Update the [change log](CHANGELOG.md)
|
255
291
|
- Commit your changes with a meaningful commit message
|
256
292
|
- Create a pull request
|
257
293
|
|
258
294
|
Thank you!
|
259
295
|
|
260
|
-
See the
|
296
|
+
See the
|
261
297
|
[list of contributors](https://github.com/Devex/article_json/contributors).
|
262
298
|
|
263
|
-
|
299
|
+
## Tests
|
264
300
|
For the whole test suite, run `bundle exec rspec`.
|
265
301
|
|
266
302
|
For individual tests, run `bundle exec rspec spec/article_json/version_spec.rb`.
|
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
4
|
+
#
|
5
|
+
# Simple script to read a JSON document and export it to Apple News.
|
6
|
+
#
|
7
|
+
# Usage:
|
8
|
+
#
|
9
|
+
# ./bin/article_json_export_apple_news.rb < my_document.json
|
10
|
+
#
|
11
|
+
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
12
|
+
|
13
|
+
require 'bundler/setup'
|
14
|
+
require_relative '../lib/article_json'
|
15
|
+
puts ArticleJSON::Article.from_json(ARGF.read).to_apple_news
|
@@ -0,0 +1,41 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
4
|
+
#
|
5
|
+
# Script to check that google doc export works as expected.
|
6
|
+
#
|
7
|
+
# Usage:
|
8
|
+
#
|
9
|
+
# ./bin/check_google_doc_export.rb
|
10
|
+
#
|
11
|
+
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
12
|
+
|
13
|
+
require 'bundler/setup'
|
14
|
+
require 'net/http'
|
15
|
+
require 'uri'
|
16
|
+
require_relative '../lib/article_json'
|
17
|
+
|
18
|
+
doc_id = '1E4lncZE2jDkbE34eDyYQmXKA9O26BHUiwguz4S9qyE8'
|
19
|
+
url =
|
20
|
+
"https://docs.google.com/feeds/download/documents/export/Export?id=#{doc_id}&exportFormat=html"
|
21
|
+
parsed_exported_doc = JSON.parse(
|
22
|
+
ArticleJSON::Article
|
23
|
+
.from_google_doc_html(Net::HTTP.get(URI.parse(url)))
|
24
|
+
.to_json
|
25
|
+
)
|
26
|
+
parsed_expected_doc = JSON.parse(File.read('spec/fixtures/reference_document_parsed.json'))
|
27
|
+
|
28
|
+
# `source_url` (for hosted images) is dynamic, so we need to remove it from the comparison`
|
29
|
+
def nullify_source_url(hash)
|
30
|
+
hash['content'].each { |element| element['source_url'] = nil if element['source_url'] }
|
31
|
+
hash
|
32
|
+
end
|
33
|
+
|
34
|
+
parsed_exported_doc = nullify_source_url(parsed_exported_doc)
|
35
|
+
parsed_expected_doc = nullify_source_url(parsed_expected_doc)
|
36
|
+
|
37
|
+
if parsed_exported_doc != parsed_expected_doc
|
38
|
+
raise StandardError, "Google doc export doesn't work as expected"
|
39
|
+
end
|
40
|
+
|
41
|
+
puts 'Google doc export worked as expected'
|
@@ -2,12 +2,10 @@
|
|
2
2
|
|
3
3
|
curl -X GET "https://vimeo.com/api/oembed.json?url=https://vimeo.com/42315417" | jq > spec/fixtures/vimeo_video_oembed.json
|
4
4
|
|
5
|
-
curl -X GET "
|
5
|
+
curl -X GET "https://www.youtube.com/oembed?format=json&url=https://www.youtube.com/watch?v=_ZG8HBuDjgc" | jq > spec/fixtures/youtube_video_oembed.json
|
6
6
|
|
7
7
|
curl -X GET "https://www.slideshare.net/api/oembed/2?format=json&url=https://www.slideshare.net/Devex/the-best-global-development-quotes-of-2012" | jq > spec/fixtures/slideshare_oembed.json
|
8
8
|
|
9
9
|
curl -X GET "https://api.twitter.com/1/statuses/oembed.json?align=center&url=https://twitter.com/d3v3x/status/554608639030599681" | jq > spec/fixtures/tweet_oembed.json
|
10
10
|
|
11
11
|
curl -X GET 'https://soundcloud.com/oembed?format=json&url=https://soundcloud.com/rich-the-kid/plug-walk-1' | jq > spec/fixtures/soundcloud_oembed.json
|
12
|
-
|
13
|
-
curl -X GET 'https://www.facebook.com/plugins/video/oembed.json?url=https://www.facebook.com/facebook/videos/1814600831891266' | jq > spec/fixtures/facebook_video_oembed.json
|
@@ -9,6 +9,7 @@ JSON_FILE="spec/fixtures/reference_document_parsed.json"
|
|
9
9
|
HTML_EXPORT_FILE="spec/fixtures/reference_document_exported.html"
|
10
10
|
AMP_EXPORT_FILE="spec/fixtures/reference_document_exported.amp.html"
|
11
11
|
FACEBOOK_EXPORT_FILE="spec/fixtures/reference_document_exported.facebook.html"
|
12
|
+
APPLE_NEWS_EXPORT_FILE="spec/fixtures/reference_document_exported.apple_news.json"
|
12
13
|
PLAIN_TEXT_EXPORT_FILE="spec/fixtures/reference_document_exported.txt"
|
13
14
|
|
14
15
|
# export the google doc to HTML
|
@@ -26,5 +27,8 @@ PLAIN_TEXT_EXPORT_FILE="spec/fixtures/reference_document_exported.txt"
|
|
26
27
|
# convert the JSON export to Facebook Instant Article
|
27
28
|
./bin/article_json_export_facebook.rb < ${JSON_FILE} > ${FACEBOOK_EXPORT_FILE}
|
28
29
|
|
30
|
+
# convert the JSON export to Apple News
|
31
|
+
./bin/article_json_export_apple_news.rb < ${JSON_FILE} > ${APPLE_NEWS_EXPORT_FILE}
|
32
|
+
|
29
33
|
# convert the JSON export to plain text
|
30
34
|
./bin/article_json_export_plain_text.rb < ${JSON_FILE} > ${PLAIN_TEXT_EXPORT_FILE}
|
data/lib/article_json/article.rb
CHANGED
@@ -14,7 +14,7 @@ module ArticleJSON
|
|
14
14
|
def elements
|
15
15
|
@elements ||= begin
|
16
16
|
if @additional_elements.any?
|
17
|
-
|
17
|
+
@additional_element_placer_class
|
18
18
|
.new(@article_elements, @additional_elements)
|
19
19
|
.merge_elements
|
20
20
|
else
|
@@ -62,6 +62,18 @@ module ArticleJSON
|
|
62
62
|
amp_exporter.html
|
63
63
|
end
|
64
64
|
|
65
|
+
# Exporter instance for AppleNews
|
66
|
+
# @return [ArticleJSON::Export::AppleNews::Exporter]
|
67
|
+
def apple_news_exporter
|
68
|
+
ArticleJSON::Export::AppleNews::Exporter.new(elements)
|
69
|
+
end
|
70
|
+
|
71
|
+
# AppleNews export of the article
|
72
|
+
# @return [String]
|
73
|
+
def to_apple_news
|
74
|
+
apple_news_exporter.to_json
|
75
|
+
end
|
76
|
+
|
65
77
|
# Exporter instance for FacebookInstantArticle
|
66
78
|
# @return [ArticleJSON::Export::FacebookInstantArticle::Exporter]
|
67
79
|
def facebook_instant_article_exporter
|
@@ -91,10 +103,18 @@ module ArticleJSON
|
|
91
103
|
# article. If the method is called multiple times, the order of additional
|
92
104
|
# elements is maintained.
|
93
105
|
# @param [Object] additional_elements
|
94
|
-
|
106
|
+
# @param [Class<#merge_elements>] with - The passes class's `#initialize` method needs
|
107
|
+
# to accept two lists of elements. See
|
108
|
+
# `ArticleJSON::Utils::AdditionalElementPlacer`
|
109
|
+
# for reference.
|
110
|
+
def place_additional_elements(
|
111
|
+
additional_elements,
|
112
|
+
with: ArticleJSON::Utils::AdditionalElementPlacer
|
113
|
+
)
|
95
114
|
# Reset the `#elements` method memoization
|
96
115
|
@elements = nil
|
97
116
|
@additional_elements.concat(additional_elements)
|
117
|
+
@additional_element_placer_class = with
|
98
118
|
end
|
99
119
|
|
100
120
|
class << self
|
@@ -14,10 +14,11 @@ module ArticleJSON
|
|
14
14
|
end
|
15
15
|
|
16
16
|
class Configuration
|
17
|
-
attr_accessor :oembed_user_agent
|
17
|
+
attr_accessor :oembed_user_agent, :facebook_token
|
18
18
|
|
19
19
|
def initialize
|
20
20
|
@oembed_user_agent = nil
|
21
|
+
@facebook_token = nil
|
21
22
|
@custom_element_exporters = {}
|
22
23
|
end
|
23
24
|
|
@@ -69,7 +69,7 @@ module ArticleJSON
|
|
69
69
|
|
70
70
|
# @return [Nokogiri::XML::Element]
|
71
71
|
def facebook_node
|
72
|
-
url = "#{@element.oembed_data[:author_url]}videos/#{@element.embed_id}"
|
72
|
+
url = "#{@element.oembed_data[:author_url]}/videos/#{@element.embed_id}"
|
73
73
|
create_element('amp-facebook',
|
74
74
|
'data-embedded-as' => 'video',
|
75
75
|
'data-href' => url,
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module ArticleJSON
|
2
|
+
module Export
|
3
|
+
module AppleNews
|
4
|
+
module Elements
|
5
|
+
class Base
|
6
|
+
include ArticleJSON::Export::Common::Elements::Base
|
7
|
+
|
8
|
+
# Export the given element. Dynamically looks up the right
|
9
|
+
# export-element-class, instantiates it and then calls the `#export`
|
10
|
+
# method.
|
11
|
+
# Defaults to nil, e.g. if no exporter is specified for the given
|
12
|
+
# type.
|
13
|
+
# @return [String]
|
14
|
+
def export
|
15
|
+
super || nil
|
16
|
+
end
|
17
|
+
|
18
|
+
class << self
|
19
|
+
# Return the module namespace this class and its subclasses are
|
20
|
+
# nested within.
|
21
|
+
# @return [Module]
|
22
|
+
def namespace
|
23
|
+
ArticleJSON::Export::AppleNews::Elements
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
# The format this exporter is returning. This is used to determine
|
29
|
+
# which custom element exporters should be applied from the
|
30
|
+
# configuration.
|
31
|
+
# @return [Symbol]
|
32
|
+
def export_format
|
33
|
+
:apple_news
|
34
|
+
end
|
35
|
+
|
36
|
+
def default_exporter_mapping
|
37
|
+
{
|
38
|
+
text: namespace::Text,
|
39
|
+
paragraph: namespace::Paragraph,
|
40
|
+
heading: namespace::Heading,
|
41
|
+
quote: namespace::Quote,
|
42
|
+
list: namespace::List,
|
43
|
+
image: namespace::Image,
|
44
|
+
embed: namespace::Embed,
|
45
|
+
text_box: namespace::TextBox,
|
46
|
+
}
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|