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.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +24 -0
  3. data/README.md +108 -72
  4. data/bin/article_json_export_amp.rb +1 -0
  5. data/bin/article_json_export_apple_news.rb +15 -0
  6. data/bin/article_json_export_facebook.rb +1 -0
  7. data/bin/article_json_export_html.rb +1 -0
  8. data/bin/article_json_export_plain_text.rb +1 -0
  9. data/bin/article_json_parse_google_doc.rb +1 -0
  10. data/bin/check_google_doc_export.rb +41 -0
  11. data/bin/update_oembed_request-stubs.sh +1 -3
  12. data/bin/update_reference_document.sh +4 -0
  13. data/lib/article_json/article.rb +22 -2
  14. data/lib/article_json/configuration.rb +2 -1
  15. data/lib/article_json/elements/base.rb +0 -1
  16. data/lib/article_json/export/amp/elements/embed.rb +1 -1
  17. data/lib/article_json/export/apple_news/elements/base.rb +53 -0
  18. data/lib/article_json/export/apple_news/elements/embed.rb +130 -0
  19. data/lib/article_json/export/apple_news/elements/heading.rb +32 -0
  20. data/lib/article_json/export/apple_news/elements/image.rb +58 -0
  21. data/lib/article_json/export/apple_news/elements/list.rb +67 -0
  22. data/lib/article_json/export/apple_news/elements/paragraph.rb +36 -0
  23. data/lib/article_json/export/apple_news/elements/quote.rb +60 -0
  24. data/lib/article_json/export/apple_news/elements/text.rb +42 -0
  25. data/lib/article_json/export/apple_news/elements/text_box.rb +51 -0
  26. data/lib/article_json/export/apple_news/exporter.rb +37 -0
  27. data/lib/article_json/import/google_doc/html/image_parser.rb +16 -2
  28. data/lib/article_json/import/google_doc/html/node_analyzer.rb +11 -1
  29. data/lib/article_json/import/google_doc/html/parser.rb +6 -1
  30. data/lib/article_json/utils/o_embed_resolver/facebook_video.rb +17 -1
  31. data/lib/article_json/utils/o_embed_resolver/youtube_video.rb +1 -1
  32. data/lib/article_json/version.rb +1 -1
  33. data/lib/article_json.rb +11 -0
  34. metadata +33 -15
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: baf39dbf5fb3f225088927c3ea9f7d58a59a502c6c70da1546829d857760ee6a
4
- data.tar.gz: f9c60e3a2e8aadffda6525eb9acd085ee5ffcc53697cc7fec4a3c204209a571e
3
+ metadata.gz: 561ba1f1fff25cba3e32eea10bdff57757ab6776a688bc78f85ec4eafeb62b32
4
+ data.tar.gz: e72e2425f7008d24be098be9024a27f493c2f13c99577ec71d7dda953564bcef
5
5
  SHA512:
6
- metadata.gz: 28783003b3b27d4eca2e5141dd59967f0f2ee44f077726bd5935a8e9dfa49fbd482cac67d49f2bc69e66797cb6dff7c67093124887215423117df6bbed8c5840
7
- data.tar.gz: 0ee51b7975ed3621a99abe34a4d2180c327e3a1a678539aa58ed40171d8bf0cf812c0b1478c49886418fb410eb8634ac3b20c8a00ed881da2edeb5f5e7bc469f
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
- JSON Format for News Articles & Ruby Gem.
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
- [![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)
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 html-export the latest version of the reference document,
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 all the different exported versions of the reference
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
- request, but these may change over time. To update them, run:
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
- There are some configuration options that allow a more tailored usage of the
73
- `article_json` gem. The following code snippet gives an example for every
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
- # PlainText exporters:
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 [Reference Document](https://docs.google.com/document/d/1E4lncZE2jDkbE34eDyYQmXKA9O26BHUiwguz4S9qyE8/edit?usp=sharing)
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
- `article_json` supports this via `article.place_additional_elements` which accepts an array of elements that you can define in your own code.
122
- Each element that is added this way will directly get placed in between paragraphs of the article.
123
- The method ensures that an additional element is never added before or after any node other than paragraphs (e.g. an image).
124
- The elements are added in the order you pass them into the method.
125
- If the article should not have enough spaces to place all the provided elements, they will be placed after the last element in the article.
126
-
127
- You can pass any type of element into this method.
128
- 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 get them rendered.
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 a HTML string for a list of elements. An example of
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
- An example of
223
- the AMP HTML export for the parsed reference document can be found
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 Tests
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
- ### Tests
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`.
@@ -10,5 +10,6 @@
10
10
  #
11
11
  # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
12
12
 
13
+ require 'bundler/setup'
13
14
  require_relative '../lib/article_json'
14
15
  puts ArticleJSON::Article.from_json(ARGF.read).to_amp
@@ -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
@@ -11,5 +11,6 @@
11
11
  #
12
12
  # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
13
13
 
14
+ require 'bundler/setup'
14
15
  require_relative '../lib/article_json'
15
16
  puts ArticleJSON::Article.from_json(ARGF.read).to_facebook_instant_article
@@ -10,5 +10,6 @@
10
10
  #
11
11
  # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
12
12
 
13
+ require 'bundler/setup'
13
14
  require_relative '../lib/article_json'
14
15
  puts ArticleJSON::Article.from_json(ARGF.read).to_html
@@ -10,5 +10,6 @@
10
10
  #
11
11
  # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
12
12
 
13
+ require 'bundler/setup'
13
14
  require_relative '../lib/article_json'
14
15
  puts ArticleJSON::Article.from_json(ARGF.read).to_plain_text
@@ -10,5 +10,6 @@
10
10
  #
11
11
  # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
12
12
 
13
+ require 'bundler/setup'
13
14
  require_relative '../lib/article_json'
14
15
  puts ArticleJSON::Article.from_google_doc_html((ARGF.read)).to_json
@@ -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 "http://www.youtube.com/oembed?format=json&url=https://www.youtube.com/watch?v=_ZG8HBuDjgc" | jq > spec/fixtures/youtube_video_oembed.json
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}
@@ -14,7 +14,7 @@ module ArticleJSON
14
14
  def elements
15
15
  @elements ||= begin
16
16
  if @additional_elements.any?
17
- ArticleJSON::Utils::AdditionalElementPlacer
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
- def place_additional_elements(additional_elements)
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
 
@@ -37,4 +37,3 @@ module ArticleJSON
37
37
  end
38
38
  end
39
39
  end
40
-
@@ -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