geoblacklight 2.3.0 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +17 -48
  3. data/.rubocop.yml +1 -1
  4. data/.rubocop_todo.yml +11 -177
  5. data/app/assets/images/blacklight/arrow-circle-down.svg +1 -2
  6. data/app/assets/images/blacklight/baruch-cuny.svg +1 -4
  7. data/app/assets/images/blacklight/berkeley.svg +1 -4
  8. data/app/assets/images/blacklight/book.svg +1 -4
  9. data/app/assets/images/blacklight/bookmark.svg +1 -4
  10. data/app/assets/images/blacklight/cd-rom.svg +1 -4
  11. data/app/assets/images/blacklight/chicago.svg +1 -4
  12. data/app/assets/images/blacklight/citation.svg +3 -0
  13. data/app/assets/images/blacklight/collection.svg +3 -0
  14. data/app/assets/images/blacklight/columbia.svg +1 -4
  15. data/app/assets/images/blacklight/cornell.svg +1 -4
  16. data/app/assets/images/blacklight/dvd-rom.svg +1 -4
  17. data/app/assets/images/blacklight/email.svg +1 -4
  18. data/app/assets/images/blacklight/esri-globe.svg +1 -4
  19. data/app/assets/images/blacklight/globe.svg +1 -2
  20. data/app/assets/images/blacklight/harvard.svg +1 -4
  21. data/app/assets/images/blacklight/home.svg +1 -2
  22. data/app/assets/images/blacklight/illinois.svg +1 -4
  23. data/app/assets/images/blacklight/image.svg +1 -4
  24. data/app/assets/images/blacklight/indiana.svg +1 -4
  25. data/app/assets/images/blacklight/iowa.svg +1 -4
  26. data/app/assets/images/blacklight/leaf.svg +1 -4
  27. data/app/assets/images/blacklight/lewis-clark.svg +1 -4
  28. data/app/assets/images/blacklight/line.svg +1 -4
  29. data/app/assets/images/blacklight/map-marker.svg +1 -4
  30. data/app/assets/images/blacklight/map.svg +1 -4
  31. data/app/assets/images/blacklight/maryland.svg +1 -4
  32. data/app/assets/images/blacklight/massgis.svg +1 -4
  33. data/app/assets/images/blacklight/metadata.svg +1 -4
  34. data/app/assets/images/blacklight/michigan-state.svg +1 -4
  35. data/app/assets/images/blacklight/michigan.svg +1 -4
  36. data/app/assets/images/blacklight/minnesota.svg +1 -4
  37. data/app/assets/images/blacklight/mit.svg +1 -4
  38. data/app/assets/images/blacklight/mixed.svg +1 -4
  39. data/app/assets/images/blacklight/multilinestring.svg +1 -4
  40. data/app/assets/images/blacklight/multipoint.svg +1 -4
  41. data/app/assets/images/blacklight/multipolygon.svg +1 -4
  42. data/app/assets/images/blacklight/nyu.svg +1 -4
  43. data/app/assets/images/blacklight/ohio-state.svg +1 -4
  44. data/app/assets/images/blacklight/pagelines-brands.svg +1 -4
  45. data/app/assets/images/blacklight/paper-map.svg +1 -4
  46. data/app/assets/images/blacklight/penn-state.svg +1 -4
  47. data/app/assets/images/blacklight/point.svg +1 -4
  48. data/app/assets/images/blacklight/polygon.svg +1 -4
  49. data/app/assets/images/blacklight/polyline.svg +1 -4
  50. data/app/assets/images/blacklight/princeton.svg +1 -4
  51. data/app/assets/images/blacklight/public.svg +1 -4
  52. data/app/assets/images/blacklight/purdue.svg +1 -4
  53. data/app/assets/images/blacklight/raster.svg +1 -4
  54. data/app/assets/images/blacklight/restricted.svg +1 -4
  55. data/app/assets/images/blacklight/sms.svg +1 -4
  56. data/app/assets/images/blacklight/stanford.svg +1 -4
  57. data/app/assets/images/blacklight/table.svg +1 -4
  58. data/app/assets/images/blacklight/tags.svg +1 -2
  59. data/app/assets/images/blacklight/texas.svg +1 -4
  60. data/app/assets/images/blacklight/tufts.svg +1 -4
  61. data/app/assets/images/blacklight/ucla.svg +1 -4
  62. data/app/assets/images/blacklight/uva.svg +1 -4
  63. data/app/assets/images/blacklight/web_services.svg +1 -4
  64. data/app/assets/images/blacklight/wisconsin.svg +1 -4
  65. data/app/assets/javascripts/geoblacklight/modules/geosearch.js +1 -1
  66. data/app/assets/javascripts/geoblacklight/modules/home.js +1 -1
  67. data/app/assets/javascripts/geoblacklight/modules/item.js +20 -1
  68. data/app/assets/stylesheets/geoblacklight/_blacklight_overrides.scss +0 -9
  69. data/app/assets/stylesheets/geoblacklight/modules/item.scss +12 -0
  70. data/app/assets/stylesheets/geoblacklight/modules/results.scss +38 -29
  71. data/app/helpers/geoblacklight_helper.rb +16 -7
  72. data/app/models/concerns/geoblacklight/solr_document.rb +7 -2
  73. data/app/models/concerns/geoblacklight/solr_document/citation.rb +28 -0
  74. data/app/views/catalog/_citation.html.erb +11 -0
  75. data/app/views/catalog/_data_dictionary.html.erb +1 -1
  76. data/app/views/catalog/_document_action.html.erb +1 -1
  77. data/app/views/catalog/_document_split.html.erb +1 -1
  78. data/app/views/catalog/_home_text.html.erb +1 -1
  79. data/app/views/catalog/_index_split_default.html.erb +18 -10
  80. data/app/views/catalog/_show_default_viewer_container.html.erb +1 -1
  81. data/app/views/catalog/_web_services_wfs.html.erb +3 -3
  82. data/app/views/catalog/_web_services_wms.html.erb +3 -3
  83. data/app/views/catalog/metadata.html.erb +3 -1
  84. data/app/views/catalog/web_services.html.erb +9 -7
  85. data/app/views/relation/_ancestors.html.erb +1 -1
  86. data/app/views/relation/_descendants.html.erb +1 -1
  87. data/config/locales/geoblacklight.en.yml +43 -59
  88. data/lib/generators/geoblacklight/templates/catalog_controller.rb +1 -0
  89. data/lib/generators/geoblacklight/templates/geoblacklight.js +0 -1
  90. data/lib/generators/geoblacklight/templates/settings.yml +4 -0
  91. data/lib/geoblacklight/catalog_helper_override.rb +1 -1
  92. data/lib/geoblacklight/relation/ancestors.rb +1 -1
  93. data/lib/geoblacklight/relation/descendants.rb +1 -1
  94. data/lib/geoblacklight/version.rb +1 -1
  95. data/lib/geoblacklight/view_helper_override.rb +1 -1
  96. data/lib/tasks/geoblacklight.rake +1 -1
  97. data/spec/features/relations_spec.rb +2 -1
  98. data/spec/features/split_view.html.erb_spec.rb +1 -1
  99. data/spec/helpers/geoblacklight_helper_spec.rb +13 -0
  100. data/spec/javascripts/geoblacklight_spec.js +0 -4
  101. data/spec/lib/geoblacklight/relation/ancestors_spec.rb +1 -1
  102. data/spec/lib/geoblacklight/relation/descendants_spec.rb +1 -1
  103. data/spec/models/concerns/geoblacklight/solr_document/citation_spec.rb +13 -0
  104. data/spec/models/concerns/geoblacklight/solr_document_spec.rb +26 -0
  105. data/spec/support/fixtures.rb +7 -0
  106. data/spec/tasks/geoblacklight_spec.rb +18 -0
  107. data/vendor/assets/javascripts/readmore.js +0 -618
  108. data/vendor/assets/javascripts/readmore.min.js +0 -0
  109. data/vendor/assets/stylesheets/leaflet.css +0 -1
  110. metadata +13 -4
  111. data/app/assets/javascripts/geoblacklight/modules/collapse.js +0 -7
  112. data/vendor/assets/javascripts/readmore.js.map +0 -1
@@ -4,7 +4,7 @@
4
4
  <% @relations.ancestors['docs'].each do |ancestor| %>
5
5
  <li class="list-group-item">
6
6
  <%= link_to solr_document_path(ancestor['layer_slug_s']) do %>
7
- <%= geoblacklight_icon('pagelines-brands') %>
7
+ <%= relations_icon(ancestor, 'pagelines-brands') %>
8
8
  <%= ancestor['dc_title_s'] %>
9
9
  <% end %>
10
10
  </li>
@@ -4,7 +4,7 @@
4
4
  <% @relations.descendants['docs'][0..2].each do |descendant| %>
5
5
  <li class="list-group-item">
6
6
  <%= link_to solr_document_path(descendant['layer_slug_s']) do %>
7
- <%= geoblacklight_icon('leaf') %>
7
+ <%= relations_icon(descendant, 'leaf') %>
8
8
  <%= descendant['dc_title_s'] %>
9
9
  <% end %>
10
10
  </li>
@@ -1,6 +1,8 @@
1
1
  en:
2
2
  geoblacklight:
3
3
  bbox_label: 'Bounding Box'
4
+ citation:
5
+ retrieved_from: 'Retrieved from %{document_url}'
4
6
  download:
5
7
  download: 'Download'
6
8
  download_link: 'Original %{download_format}'
@@ -40,6 +42,8 @@ en:
40
42
  jpg: 'JPG'
41
43
  esri_geodatabase: 'ESRI Geodatabase'
42
44
  sqlite_database: 'SQLite Database'
45
+ map:
46
+ label: 'Zoomable map'
43
47
  references:
44
48
  wms: 'Web Mapping Service (WMS)'
45
49
  wms_abv: 'WMS'
@@ -102,62 +106,42 @@ en:
102
106
  wms:
103
107
  title: Web Map Service (WMS)
104
108
  content: A Web Map Service displays a geospatial dataset as map images.
105
- aria-labels:
106
- arrow-circle-down: Arrow within a circle, pointing down (icon)
107
- baruch-cuny: Baruch College (logo)
108
- berkeley: University of California, Berkeley (logo)
109
- book: Book (icon)
110
- bookmark: Bookmark (icon)
111
- cd-rom: CD-Rom (icon)
112
- chicago: The University of Chicago (logo)
113
- columbia: Columbia University (logo)
114
- cornell: Cornell University (logo)
115
- dvd-rom: DVD-Rom (icon)
116
- email: Email (icon)
117
- esri-globe: Esri Global (logo)
118
- globe: Globe (icon)
119
- harvard: Harvard University (logo)
120
- home: Home (icon)
121
- illinois: University of Illinois (logo)
122
- image: Image (icon)
123
- indiana: Indiana University (logo)
124
- iowa: University of Iowa (logo)
125
- leaf: Leaf (icon)
126
- lewis-clark: Lewis & Clark (logo)
127
- line: Line (icon)
128
- map-marker: Map marker (icon)
129
- map: Map (icon)
130
- maryland: University of Maryland (logo)
131
- massgis: MassGIS (logo)
132
- metadata: Metadata (icon)
133
- michigan-state: Michigan State University (logo)
134
- michigan: University of Michigan (logo)
135
- minnesota: University of Minnesota (logo)
136
- mit: Massachusetts Institute of Technology (logo)
137
- mixed: Mixed (icon)
138
- multilinestring: Multi-line string (icon)
139
- multipoint: Multi-point (icon)
140
- multipolygon: Multi-polygon (icon)
141
- nyu: New York University (logo)
142
- ohio-state: The Ohio State University (logo)
143
- pagelines-brands: Pagelines brands (icon)
144
- paper-map: Paper map (icon)
145
- penn-state: Penn State University (logo)
146
- point: Point (icon)
147
- polygon: Polygon (icon)
148
- polyline: Polyline (icon)
149
- princeton: Princeton University (logo)
150
- public: Public content (icon)
151
- purdue: Purdue University (logo)
152
- raster: Raster (icon)
153
- restricted: Restricted content (icon)
154
- sms: SMS (icon)
155
- stanford: Stanford University (logo)
156
- table: Table (icon)
157
- tags: Tags (icon)
158
- texas: The University of Texas at Austin (logo)
159
- tufts: Tufts University (logo)
160
- ucla: University of California, Los Angeles (logo)
161
- uva: University of Virginia (logo)
162
- web_services: Web services (icon)
163
- wisconsin: University of Wisconsin (logo)
109
+ blacklight:
110
+ icon:
111
+ arrow-circle-down: Arrow within a circle, pointing down
112
+ baruch-cuny: Baruch College
113
+ berkeley: University of California, Berkeley
114
+ cd-rom: CD-Rom
115
+ chicago: The University of Chicago
116
+ columbia: Columbia University
117
+ cornell: Cornell University
118
+ dvd-rom: DVD-Rom
119
+ esri-globe: Esri Global
120
+ harvard: Harvard University
121
+ illinois: University of Illinois
122
+ indiana: Indiana University
123
+ iowa: University of Iowa
124
+ lewis-clark: Lewis & Clark
125
+ maryland: University of Maryland
126
+ massgis: MassGIS
127
+ michigan-state: Michigan State University
128
+ michigan: University of Michigan
129
+ minnesota: University of Minnesota
130
+ mit: Massachusetts Institute of Technology
131
+ multilinestring: Multi-line string
132
+ multipoint: Multi-point
133
+ multipolygon: Multi-polygon
134
+ nyu: New York University
135
+ ohio-state: The Ohio State University
136
+ penn-state: Penn State University
137
+ princeton: Princeton University
138
+ public: Public content
139
+ purdue: Purdue University
140
+ restricted: Restricted content
141
+ sms: SMS
142
+ stanford: Stanford University
143
+ texas: The University of Texas at Austin
144
+ tufts: Tufts University
145
+ ucla: University of California, Los Angeles
146
+ uva: University of Virginia
147
+ wisconsin: University of Wisconsin
@@ -238,6 +238,7 @@ class CatalogController < ApplicationController
238
238
  config.add_results_collection_tool(:sort_widget)
239
239
  config.add_results_collection_tool(:per_page_widget)
240
240
  config.add_show_tools_partial(:bookmark, partial: 'bookmark_control', if: :render_bookmarks_control?)
241
+ config.add_show_tools_partial(:citation)
241
242
  config.add_show_tools_partial(:email, callback: :email_action, validator: :validate_email_params)
242
243
  config.add_show_tools_partial(:sms, if: :render_sms_action?, callback: :sms_action, validator: :validate_sms_params)
243
244
 
@@ -7,4 +7,3 @@
7
7
  //= require geoblacklight/downloaders
8
8
  //= require leaflet-iiif
9
9
  //= require esri-leaflet
10
- //= require readmore
@@ -44,6 +44,7 @@ FIELDS:
44
44
  :TEMPORAL: 'dct_temporal_sm'
45
45
  :TITLE: 'dc_title_s'
46
46
  :SOURCE: 'dc_source_sm'
47
+ :ISSUED: 'dct_issued_s'
47
48
 
48
49
  # Institution deployed at
49
50
  INSTITUTION: 'Stanford'
@@ -61,6 +62,9 @@ TIMEOUT_DOWNLOAD: 16
61
62
  # (For WMS inspection) timeout and open_timeout parameters for Faraday
62
63
  TIMEOUT_WMS: 4
63
64
 
65
+ # Use the geometry type for the data relations icon
66
+ USE_GEOM_FOR_RELATIONS_ICON: false
67
+
64
68
  # Web services shown in tool panel
65
69
  WEBSERVICES_SHOWN:
66
70
  - 'wms'
@@ -5,7 +5,7 @@ module Geoblacklight
5
5
  # @param [Symbol] symbol of field to be removed
6
6
  # @param [Hash] request parameters
7
7
  def remove_spatial_filter_group(field, source_params = params)
8
- p = source_params.dup
8
+ p = source_params.dup.to_h
9
9
  p.delete(field.to_s)
10
10
  p
11
11
  end
@@ -8,7 +8,7 @@ module Geoblacklight
8
8
 
9
9
  def create_search_params
10
10
  { fq: ["{!join from=#{Settings.FIELDS.SOURCE} to=layer_slug_s}layer_slug_s:#{@search_id}"],
11
- fl: [Settings.FIELDS.TITLE, 'layer_slug_s'] }
11
+ fl: [Settings.FIELDS.TITLE, 'layer_slug_s', Settings.FIELDS.GEOM_TYPE] }
12
12
  end
13
13
 
14
14
  def execute_query
@@ -8,7 +8,7 @@ module Geoblacklight
8
8
 
9
9
  def create_search_params
10
10
  { fq: "#{Settings.FIELDS.SOURCE}:#{@search_id}",
11
- fl: [Settings.FIELDS.TITLE, 'layer_slug_s'] }
11
+ fl: [Settings.FIELDS.TITLE, 'layer_slug_s', Settings.FIELDS.GEOM_TYPE] }
12
12
  end
13
13
 
14
14
  def execute_query
@@ -1,3 +1,3 @@
1
1
  module Geoblacklight
2
- VERSION = '2.3.0'.freeze
2
+ VERSION = '2.4.0'.freeze
3
3
  end
@@ -26,7 +26,7 @@ module Geoblacklight
26
26
 
27
27
  def render_constraints_filters(localized_params = params)
28
28
  content = super(localized_params)
29
- localized_params = localized_params.to_unsafe_h unless localized_params.is_a?(Hash)
29
+ localized_params = localized_params.to_unsafe_h if localized_params.respond_to?(:to_unsafe_h)
30
30
 
31
31
  if localized_params[:bbox]
32
32
  path = search_action_path(remove_spatial_filter_group(:bbox, localized_params))
@@ -78,7 +78,7 @@ namespace :geoblacklight do
78
78
  end
79
79
  desc 'Create download directory'
80
80
  task mkdir: :environment do
81
- FileUtils.mkdir_p Dir.glob("#{Rails.root}/tmp/cache/downloads")
81
+ FileUtils.mkdir_p Rails.root.join('tmp/cache/downloads'), verbose: true
82
82
  end
83
83
  desc 'Precaches a download'
84
84
  task :precache, [:doc_id, :download_type, :timeout] => [:environment] do |t, args|
@@ -17,7 +17,8 @@ feature 'Display related documents' do
17
17
  [
18
18
  {
19
19
  'dc_title_s' => '2015 New York City Subway Complexes and Ridership',
20
- 'layer_slug_s' => 'nyu_2451_34502'
20
+ 'layer_slug_s' => 'nyu_2451_34502',
21
+ 'layer_geom_type_s' => 'Point'
21
22
  }
22
23
  ]
23
24
  },
@@ -53,7 +53,7 @@ feature 'Index view', js: true do
53
53
  scenario 'click on a record area to expand collapse' do
54
54
  within('.documentHeader', match: :first) do
55
55
  expect(page).not_to have_css('.collapse')
56
- find('.status-icons').click
56
+ find('button').click
57
57
  expect(page).to have_css('.collapse', visible: true)
58
58
  end
59
59
  end
@@ -326,4 +326,17 @@ describe GeoblacklightHelper, type: :helper do
326
326
  end
327
327
  end
328
328
  end
329
+
330
+ describe '#relations_icon' do
331
+ it 'renders a goemetry type if configured' do
332
+ allow(Settings).to receive(:USE_GEOM_FOR_RELATIONS_ICON).and_return(true)
333
+ html = Capybara.string(helper.relations_icon({ 'layer_geom_type_s' => 'polygon' }, 'leaf'))
334
+ expect(html.title.strip).to eq 'Polygon'
335
+ end
336
+ it 'renders provided icon if not configured to use geometry' do
337
+ allow(Settings).to receive(:USE_GEOM_FOR_RELATIONS_ICON).and_return(false)
338
+ html = Capybara.string(helper.relations_icon({ 'layer_geom_type_s' => 'polygon' }, 'leaf'))
339
+ expect(html.title.strip).to eq 'Leaf'
340
+ end
341
+ end
329
342
  end
@@ -13,9 +13,5 @@ describe('GeoBlacklight', function() {
13
13
  it('MetadataDownloadButton is defined', function() {
14
14
  expect(GeoBlacklight.MetadataDownloadButton).toBeDefined();
15
15
  });
16
-
17
- it ('Readmore is defined', function() {
18
- expect(Readmore).toBeDefined();
19
- });
20
16
  });
21
17
  });
@@ -7,7 +7,7 @@ describe Geoblacklight::Relation::Ancestors do
7
7
 
8
8
  describe '#create_search_params' do
9
9
  it 'assembles the correct search params for finding ancestor documents' do
10
- expect(ancestors.create_search_params).to eq(fq: ["{!join from=#{Settings.FIELDS.SOURCE} to=layer_slug_s}layer_slug_s:nyu_2451_34502"], fl: [Settings.FIELDS.TITLE.to_s, 'layer_slug_s'])
10
+ expect(ancestors.create_search_params).to eq(fq: ["{!join from=#{Settings.FIELDS.SOURCE} to=layer_slug_s}layer_slug_s:nyu_2451_34502"], fl: [Settings.FIELDS.TITLE.to_s, 'layer_slug_s', 'layer_geom_type_s'])
11
11
  end
12
12
  end
13
13
 
@@ -7,7 +7,7 @@ describe Geoblacklight::Relation::Descendants do
7
7
 
8
8
  describe '#create_search_params' do
9
9
  it 'assembles the correct search params for finding descendant documents' do
10
- expect(descendants.create_search_params).to eq(fq: "#{Settings.FIELDS.SOURCE}:nyu_2451_34636", fl: [Settings.FIELDS.TITLE.to_s, 'layer_slug_s'])
10
+ expect(descendants.create_search_params).to eq(fq: "#{Settings.FIELDS.SOURCE}:nyu_2451_34636", fl: [Settings.FIELDS.TITLE.to_s, 'layer_slug_s', 'layer_geom_type_s'])
11
11
  end
12
12
  end
13
13
 
@@ -0,0 +1,13 @@
1
+ require 'spec_helper'
2
+
3
+ describe Geoblacklight::SolrDocument::Citation do
4
+ describe '#geoblacklight_citation' do
5
+ let(:fixture) { JSON.parse(read_fixture('solr_documents/restricted-line.json')) }
6
+ let(:document) { SolrDocument.new(fixture) }
7
+
8
+ it 'creates a citation' do
9
+ expect(document.geoblacklight_citation('http://example.com'))
10
+ .to eq 'United States. National Oceanic and Atmospheric Administration. Circuit Rider Productions. (2002). 10 Meter Contours: Russian River Basin, California. [Shapefile]. Circuit Rider Productions. Retrieved from http://example.com'
11
+ end
12
+ end
13
+ end
@@ -35,6 +35,32 @@ describe Geoblacklight::SolrDocument do
35
35
  expect(document.public?).to be_falsey
36
36
  end
37
37
  end
38
+ describe 'without rights data' do
39
+ let(:document_attributes) { {} }
40
+ it 'is not public' do
41
+ expect(document.public?).to be_falsey
42
+ end
43
+ end
44
+ end
45
+ describe '#restricted?' do
46
+ describe 'a restricted document' do
47
+ let(:document_attributes) { { rights_field => 'RESTRICTED' } }
48
+ it 'is restricted' do
49
+ expect(document.restricted?).to be_truthy
50
+ end
51
+ end
52
+ describe 'a non-restricted resource' do
53
+ let(:document_attributes) { { rights_field => 'PUBLIC' } }
54
+ it 'is not restricted' do
55
+ expect(document.restricted?).to be_falsey
56
+ end
57
+ end
58
+ describe 'without rights data' do
59
+ let(:document_attributes) { {} }
60
+ it 'is restricted' do
61
+ expect(document.restricted?).to be_truthy
62
+ end
63
+ end
38
64
  end
39
65
  describe '#downloadable?' do
40
66
  describe 'available direct download' do
@@ -0,0 +1,7 @@
1
+ def read_fixture(fname)
2
+ File.read(File.join(fixture_dir, fname))
3
+ end
4
+
5
+ def fixture_dir
6
+ @fixture_dir ||= File.join(File.dirname(__FILE__), '../fixtures')
7
+ end
@@ -0,0 +1,18 @@
1
+ require 'spec_helper'
2
+ require 'rake'
3
+ require 'fileutils'
4
+
5
+ describe 'geoblacklight.rake' do
6
+ describe 'geoblacklight:downloads:mkdir' do
7
+ before do
8
+ Rails.application.load_tasks
9
+ FileUtils.rm_rf Rails.root.join('tmp/cache/downloads')
10
+ end
11
+
12
+ it 'creates the tmp/cache/downloads directory' do
13
+ Rake::Task['geoblacklight:downloads:mkdir'].invoke
14
+ expect(File.directory? Rails.root.join('tmp/cache/downloads')).
15
+ to be true
16
+ end
17
+ end
18
+ end
@@ -1,618 +0,0 @@
1
- /*!
2
- * @preserve
3
- *
4
- * Readmore.js plugin
5
- * Author: @jed_foster
6
- * Project home: jedfoster.com/Readmore.js
7
- * Version: 3.0.0-beta-1
8
- * Licensed under the MIT license
9
- *
10
- * Debounce function from davidwalsh.name/javascript-debounce-function
11
- */
12
- (function webpackUniversalModuleDefinition(root, factory) {
13
- if(typeof exports === 'object' && typeof module === 'object')
14
- module.exports = factory();
15
- else if(typeof define === 'function' && define.amd)
16
- define("Readmore", [], factory);
17
- else if(typeof exports === 'object')
18
- exports["Readmore"] = factory();
19
- else
20
- root["Readmore"] = factory();
21
- })(window, function() {
22
- return /******/ (function(modules) { // webpackBootstrap
23
- /******/ // The module cache
24
- /******/ var installedModules = {};
25
- /******/
26
- /******/ // The require function
27
- /******/ function __webpack_require__(moduleId) {
28
- /******/
29
- /******/ // Check if module is in cache
30
- /******/ if(installedModules[moduleId]) {
31
- /******/ return installedModules[moduleId].exports;
32
- /******/ }
33
- /******/ // Create a new module (and put it into the cache)
34
- /******/ var module = installedModules[moduleId] = {
35
- /******/ i: moduleId,
36
- /******/ l: false,
37
- /******/ exports: {}
38
- /******/ };
39
- /******/
40
- /******/ // Execute the module function
41
- /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
42
- /******/
43
- /******/ // Flag the module as loaded
44
- /******/ module.l = true;
45
- /******/
46
- /******/ // Return the exports of the module
47
- /******/ return module.exports;
48
- /******/ }
49
- /******/
50
- /******/
51
- /******/ // expose the modules object (__webpack_modules__)
52
- /******/ __webpack_require__.m = modules;
53
- /******/
54
- /******/ // expose the module cache
55
- /******/ __webpack_require__.c = installedModules;
56
- /******/
57
- /******/ // define getter function for harmony exports
58
- /******/ __webpack_require__.d = function(exports, name, getter) {
59
- /******/ if(!__webpack_require__.o(exports, name)) {
60
- /******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
61
- /******/ }
62
- /******/ };
63
- /******/
64
- /******/ // define __esModule on exports
65
- /******/ __webpack_require__.r = function(exports) {
66
- /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
67
- /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
68
- /******/ }
69
- /******/ Object.defineProperty(exports, '__esModule', { value: true });
70
- /******/ };
71
- /******/
72
- /******/ // create a fake namespace object
73
- /******/ // mode & 1: value is a module id, require it
74
- /******/ // mode & 2: merge all properties of value into the ns
75
- /******/ // mode & 4: return value when already ns object
76
- /******/ // mode & 8|1: behave like require
77
- /******/ __webpack_require__.t = function(value, mode) {
78
- /******/ if(mode & 1) value = __webpack_require__(value);
79
- /******/ if(mode & 8) return value;
80
- /******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
81
- /******/ var ns = Object.create(null);
82
- /******/ __webpack_require__.r(ns);
83
- /******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
84
- /******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
85
- /******/ return ns;
86
- /******/ };
87
- /******/
88
- /******/ // getDefaultExport function for compatibility with non-harmony modules
89
- /******/ __webpack_require__.n = function(module) {
90
- /******/ var getter = module && module.__esModule ?
91
- /******/ function getDefault() { return module['default']; } :
92
- /******/ function getModuleExports() { return module; };
93
- /******/ __webpack_require__.d(getter, 'a', getter);
94
- /******/ return getter;
95
- /******/ };
96
- /******/
97
- /******/ // Object.prototype.hasOwnProperty.call
98
- /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
99
- /******/
100
- /******/ // __webpack_public_path__
101
- /******/ __webpack_require__.p = "";
102
- /******/
103
- /******/
104
- /******/ // Load entry module and return exports
105
- /******/ return __webpack_require__(__webpack_require__.s = 0);
106
- /******/ })
107
- /************************************************************************/
108
- /******/ ({
109
-
110
- /***/ "./node_modules/@babel/runtime/helpers/classCallCheck.js":
111
- /*!***************************************************************!*\
112
- !*** ./node_modules/@babel/runtime/helpers/classCallCheck.js ***!
113
- \***************************************************************/
114
- /*! no static exports found */
115
- /***/ (function(module, exports) {
116
-
117
- function _classCallCheck(instance, Constructor) {
118
- if (!(instance instanceof Constructor)) {
119
- throw new TypeError("Cannot call a class as a function");
120
- }
121
- }
122
-
123
- module.exports = _classCallCheck;
124
-
125
- /***/ }),
126
-
127
- /***/ "./node_modules/@babel/runtime/helpers/createClass.js":
128
- /*!************************************************************!*\
129
- !*** ./node_modules/@babel/runtime/helpers/createClass.js ***!
130
- \************************************************************/
131
- /*! no static exports found */
132
- /***/ (function(module, exports) {
133
-
134
- function _defineProperties(target, props) {
135
- for (var i = 0; i < props.length; i++) {
136
- var descriptor = props[i];
137
- descriptor.enumerable = descriptor.enumerable || false;
138
- descriptor.configurable = true;
139
- if ("value" in descriptor) descriptor.writable = true;
140
- Object.defineProperty(target, descriptor.key, descriptor);
141
- }
142
- }
143
-
144
- function _createClass(Constructor, protoProps, staticProps) {
145
- if (protoProps) _defineProperties(Constructor.prototype, protoProps);
146
- if (staticProps) _defineProperties(Constructor, staticProps);
147
- return Constructor;
148
- }
149
-
150
- module.exports = _createClass;
151
-
152
- /***/ }),
153
-
154
- /***/ "./node_modules/@babel/runtime/helpers/typeof.js":
155
- /*!*******************************************************!*\
156
- !*** ./node_modules/@babel/runtime/helpers/typeof.js ***!
157
- \*******************************************************/
158
- /*! no static exports found */
159
- /***/ (function(module, exports) {
160
-
161
- function _typeof2(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof2 = function _typeof2(obj) { return typeof obj; }; } else { _typeof2 = function _typeof2(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof2(obj); }
162
-
163
- function _typeof(obj) {
164
- if (typeof Symbol === "function" && _typeof2(Symbol.iterator) === "symbol") {
165
- module.exports = _typeof = function _typeof(obj) {
166
- return _typeof2(obj);
167
- };
168
- } else {
169
- module.exports = _typeof = function _typeof(obj) {
170
- return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : _typeof2(obj);
171
- };
172
- }
173
-
174
- return _typeof(obj);
175
- }
176
-
177
- module.exports = _typeof;
178
-
179
- /***/ }),
180
-
181
- /***/ "./src/readmore.js":
182
- /*!*************************!*\
183
- !*** ./src/readmore.js ***!
184
- \*************************/
185
- /*! exports provided: default */
186
- /***/ (function(module, __webpack_exports__, __webpack_require__) {
187
-
188
- "use strict";
189
- __webpack_require__.r(__webpack_exports__);
190
- /* harmony import */ var _babel_runtime_helpers_classCallCheck__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @babel/runtime/helpers/classCallCheck */ "./node_modules/@babel/runtime/helpers/classCallCheck.js");
191
- /* harmony import */ var _babel_runtime_helpers_classCallCheck__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_babel_runtime_helpers_classCallCheck__WEBPACK_IMPORTED_MODULE_0__);
192
- /* harmony import */ var _babel_runtime_helpers_createClass__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @babel/runtime/helpers/createClass */ "./node_modules/@babel/runtime/helpers/createClass.js");
193
- /* harmony import */ var _babel_runtime_helpers_createClass__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_babel_runtime_helpers_createClass__WEBPACK_IMPORTED_MODULE_1__);
194
- /* harmony import */ var _babel_runtime_helpers_typeof__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @babel/runtime/helpers/typeof */ "./node_modules/@babel/runtime/helpers/typeof.js");
195
- /* harmony import */ var _babel_runtime_helpers_typeof__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_babel_runtime_helpers_typeof__WEBPACK_IMPORTED_MODULE_2__);
196
-
197
-
198
-
199
- var uniqueIdCounter = 0;
200
- var isCssEmbeddedFor = []; // from:https://github.com/jserz/js_piece/blob/master/DOM/ChildNode/remove()/remove().md
201
-
202
- (function removePolyfill(arr) {
203
- arr.forEach(function (item) {
204
- if (Object.prototype.hasOwnProperty.call(item, 'remove')) {
205
- return;
206
- }
207
-
208
- Object.defineProperty(item, 'remove', {
209
- configurable: true,
210
- enumerable: true,
211
- writable: true,
212
- value: function remove() {
213
- if (this.parentNode !== null) {
214
- this.parentNode.removeChild(this);
215
- }
216
- }
217
- });
218
- });
219
- })([Element.prototype, CharacterData.prototype, DocumentType.prototype]);
220
-
221
- function forEach(arr, callback, scope) {
222
- for (var i = 0; i < arr.length; i += 1) {
223
- callback.call(scope, arr[i], i);
224
- }
225
- }
226
-
227
- function extend() {
228
- for (var _len = arguments.length, objects = new Array(_len), _key = 0; _key < _len; _key++) {
229
- objects[_key] = arguments[_key];
230
- }
231
-
232
- var hasProp = {}.hasOwnProperty;
233
- var child = objects[0];
234
- var parent = objects[1];
235
-
236
- if (objects.length > 2) {
237
- var args = [];
238
- Object.keys(objects).forEach(function (key) {
239
- args.push(objects[key]);
240
- });
241
-
242
- while (args.length > 2) {
243
- var c1 = args.shift();
244
- var p1 = args.shift();
245
- args.unshift(extend(c1, p1));
246
- }
247
-
248
- child = args.shift();
249
- parent = args.shift();
250
- }
251
-
252
- if (parent) {
253
- Object.keys(parent).forEach(function (key) {
254
- if (hasProp.call(parent, key)) {
255
- if (_babel_runtime_helpers_typeof__WEBPACK_IMPORTED_MODULE_2___default()(parent[key]) === 'object') {
256
- child[key] = child[key] || {};
257
- child[key] = extend(child[key], parent[key]);
258
- } else {
259
- child[key] = parent[key];
260
- }
261
- }
262
- });
263
- }
264
-
265
- return child;
266
- }
267
-
268
- function debounce(func, wait, immediate) {
269
- var timeout;
270
- return function debouncedFunc() {
271
- var _this = this;
272
-
273
- for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
274
- args[_key2] = arguments[_key2];
275
- }
276
-
277
- var callNow = immediate && !timeout;
278
-
279
- var later = function later() {
280
- timeout = null;
281
- if (!immediate) func.apply(_this, args);
282
- };
283
-
284
- clearTimeout(timeout);
285
- timeout = setTimeout(later, wait);
286
- if (callNow) func.apply(this, args);
287
- };
288
- }
289
-
290
- function uniqueId() {
291
- uniqueIdCounter += 1;
292
- return "rmjs-".concat(uniqueIdCounter);
293
- }
294
-
295
- function setBoxHeights(element) {
296
- element.style.height = 'auto';
297
- var expandedHeight = parseInt(element.getBoundingClientRect().height, 10);
298
- var cssMaxHeight = parseInt(window.getComputedStyle(element).maxHeight, 10);
299
- var defaultHeight = parseInt(element.readmore.defaultHeight, 10); // Store our measurements.
300
-
301
- element.readmore.expandedHeight = expandedHeight;
302
- element.readmore.maxHeight = cssMaxHeight;
303
- element.readmore.collapsedHeight = cssMaxHeight || element.readmore.collapsedHeight || defaultHeight;
304
- element.style.maxHeight = 'none';
305
- }
306
-
307
- function createElementFromString(htmlString) {
308
- var div = document.createElement('div');
309
- div.innerHTML = htmlString;
310
- return div.firstChild;
311
- }
312
-
313
- function embedCSS(selector, options) {
314
- if (!isCssEmbeddedFor[selector]) {
315
- var styles = '';
316
-
317
- if (options.embedCSS && options.blockCSS !== '') {
318
- styles += "".concat(selector, " + [data-readmore-toggle], ").concat(selector, "[data-readmore] {\n ").concat(options.blockCSS, "\n }");
319
- } // Include the transition CSS even if embedCSS is false
320
-
321
-
322
- styles += "".concat(selector, "[data-readmore] {\n transition: height ").concat(options.speed, "ms;\n overflow: hidden;\n }");
323
-
324
- (function (d, u) {
325
- var css = d.createElement('style');
326
- css.type = 'text/css';
327
-
328
- if (css.styleSheet) {
329
- css.styleSheet.cssText = u;
330
- } else {
331
- css.appendChild(d.createTextNode(u));
332
- }
333
-
334
- d.getElementsByTagName('head')[0].appendChild(css);
335
- })(document, styles);
336
-
337
- isCssEmbeddedFor[selector] = true;
338
- }
339
- }
340
-
341
- function buildToggle(link, element, scope) {
342
- function clickHandler(event) {
343
- this.toggle(element, event);
344
- }
345
-
346
- var text = link;
347
-
348
- if (typeof link === 'function') {
349
- text = link(element);
350
- }
351
-
352
- var toggleLink = createElementFromString(text);
353
- toggleLink.setAttribute('data-readmore-toggle', element.id);
354
- toggleLink.setAttribute('aria-controls', element.id);
355
- toggleLink.addEventListener('click', clickHandler.bind(scope));
356
- return toggleLink;
357
- }
358
-
359
- function isEnvironmentSupported() {
360
- return typeof window !== 'undefined' && typeof document !== 'undefined' && !!document.querySelectorAll && !!window.addEventListener;
361
- }
362
-
363
- var resizeBoxes = debounce(function () {
364
- var elements = document.querySelectorAll('[data-readmore]');
365
- forEach(elements, function (element) {
366
- var expanded = element.getAttribute('aria-expanded') === 'true';
367
- setBoxHeights(element);
368
- element.style.height = "".concat(expanded ? element.readmore.expandedHeight : element.readmore.collapsedHeight, "px");
369
- });
370
- }, 100);
371
- var defaults = {
372
- speed: 100,
373
- collapsedHeight: 200,
374
- heightMargin: 16,
375
- moreLink: '<a href="#">Read More</a>',
376
- lessLink: '<a href="#">Close</a>',
377
- embedCSS: true,
378
- blockCSS: 'display: block; width: 100%;',
379
- startOpen: false,
380
- sourceOrder: 'after',
381
- // callbacks
382
- blockProcessed: function blockProcessed() {},
383
- beforeToggle: function beforeToggle() {},
384
- afterToggle: function afterToggle() {}
385
- };
386
-
387
- var Readmore =
388
- /*#__PURE__*/
389
- function () {
390
- function Readmore() {
391
- var _this2 = this;
392
-
393
- _babel_runtime_helpers_classCallCheck__WEBPACK_IMPORTED_MODULE_0___default()(this, Readmore);
394
-
395
- if (!isEnvironmentSupported()) return;
396
-
397
- for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
398
- args[_key3] = arguments[_key3];
399
- }
400
-
401
- var selector = args[0],
402
- options = args[1];
403
- var elements;
404
-
405
- if (typeof selector === 'string') {
406
- elements = document.querySelectorAll(selector);
407
- } else if (selector.nodeName) {
408
- elements = [selector]; // emulate a NodeList by casting a single Node as an array
409
- } else {
410
- elements = selector;
411
- } // After all that, if we _still_ don't have iteratable NodeList, bail out.
412
-
413
-
414
- if (!elements.length) return;
415
- this.options = extend({}, defaults, options);
416
-
417
- if (typeof selector === 'string') {
418
- embedCSS(selector, this.options);
419
- } else {
420
- // Instances need distinct selectors so they don't stomp on each other.
421
- this.instanceSelector = ".".concat(uniqueId());
422
- embedCSS(this.instanceSelector, this.options);
423
- } // Need to resize boxes when the page has fully loaded.
424
-
425
-
426
- window.addEventListener('load', resizeBoxes);
427
- window.addEventListener('resize', resizeBoxes);
428
- this.elements = [];
429
- forEach(elements, function (element) {
430
- if (_this2.instanceSelector) {
431
- element.classList.add(_this2.instanceSelector.substr(1));
432
- }
433
-
434
- var expanded = _this2.options.startOpen;
435
- element.readmore = {
436
- defaultHeight: _this2.options.collapsedHeight,
437
- heightMargin: _this2.options.heightMargin
438
- };
439
- setBoxHeights(element);
440
- var heightMargin = element.readmore.heightMargin;
441
-
442
- if (element.getBoundingClientRect().height <= element.readmore.collapsedHeight + heightMargin) {
443
- if (typeof _this2.options.blockProcessed === 'function') {
444
- _this2.options.blockProcessed(element, false);
445
- }
446
-
447
- return;
448
- }
449
-
450
- element.setAttribute('data-readmore', '');
451
- element.setAttribute('aria-expanded', expanded);
452
- element.id = element.id || uniqueId();
453
- var toggleLink = expanded ? _this2.options.lessLink : _this2.options.moreLink;
454
- var toggleElement = buildToggle(toggleLink, element, _this2);
455
- element.parentNode.insertBefore(toggleElement, _this2.options.sourceOrder === 'before' ? element : element.nextSibling);
456
- element.style.height = "".concat(expanded ? element.readmore.expandedHeight : element.readmore.collapsedHeight, "px");
457
-
458
- if (typeof _this2.options.blockProcessed === 'function') {
459
- _this2.options.blockProcessed(element, true);
460
- }
461
-
462
- _this2.elements.push(element);
463
- });
464
- } // Signature when called internally by the toggleLink click handler:
465
- // toggle(element, event)
466
- //
467
- // When called externally by an instance,
468
- // e.g. readmoreDemo.toggle(document.querySelector('article:nth-of-type(1)')):
469
- // toggle(elementOrQuerySelector)
470
-
471
-
472
- _babel_runtime_helpers_createClass__WEBPACK_IMPORTED_MODULE_1___default()(Readmore, [{
473
- key: "toggle",
474
- value: function toggle() {
475
- var _this3 = this;
476
-
477
- var el = arguments.length <= 0 ? undefined : arguments[0];
478
-
479
- var toggleElement = function toggleElement(element) {
480
- var trigger = document.querySelector("[aria-controls=\"".concat(element.id, "\"]"));
481
- var expanded = element.getBoundingClientRect().height <= element.readmore.collapsedHeight;
482
- var newHeight = expanded ? element.readmore.expandedHeight : element.readmore.collapsedHeight; // Fire beforeToggle callback
483
- // Since we determined the new "expanded" state above we're now out of sync
484
- // with our true current state, so we need to flip the value of `expanded`
485
-
486
- if (typeof _this3.options.beforeToggle === 'function') {
487
- var shouldContinueToggle = _this3.options.beforeToggle(trigger, element, !expanded); // if the beforeToggle callback returns false, stop toggling
488
-
489
-
490
- if (shouldContinueToggle === false) {
491
- return;
492
- }
493
- }
494
-
495
- element.style.height = "".concat(newHeight, "px");
496
-
497
- var transitionendHandler = function transitionendHandler(transitionEvent) {
498
- // Fire afterToggle callback
499
- if (typeof _this3.options.afterToggle === 'function') {
500
- _this3.options.afterToggle(trigger, element, expanded);
501
- }
502
-
503
- transitionEvent.stopPropagation();
504
- element.setAttribute('aria-expanded', expanded);
505
- element.removeEventListener('transitionend', transitionendHandler, false);
506
- };
507
-
508
- element.addEventListener('transitionend', transitionendHandler, false);
509
-
510
- if (_this3.options.speed < 1) {
511
- transitionendHandler.call(_this3, {
512
- target: element
513
- });
514
- }
515
-
516
- var toggleLink = expanded ? _this3.options.lessLink : _this3.options.moreLink;
517
-
518
- if (!toggleLink) {
519
- trigger.remove();
520
- } else if (trigger && trigger.parentNode) {
521
- trigger.parentNode.replaceChild(buildToggle(toggleLink, element, _this3), trigger);
522
- }
523
- };
524
-
525
- if (typeof el === 'string') {
526
- el = document.querySelectorAll(el);
527
- }
528
-
529
- if (!el) {
530
- throw new Error('Element MUST be either an HTML node or querySelector string');
531
- }
532
-
533
- var event = arguments.length <= 1 ? undefined : arguments[1];
534
-
535
- if (event) {
536
- event.preventDefault();
537
- event.stopPropagation();
538
- }
539
-
540
- if (_babel_runtime_helpers_typeof__WEBPACK_IMPORTED_MODULE_2___default()(el) === 'object' && !el.nodeName) {
541
- // element is likely a NodeList
542
- forEach(el, toggleElement);
543
- } else {
544
- toggleElement(el);
545
- }
546
- }
547
- }, {
548
- key: "destroy",
549
- value: function destroy(selector) {
550
- var _this4 = this;
551
-
552
- var elements;
553
-
554
- if (!selector) {
555
- elements = this.elements; // eslint-disable-line
556
- } else if (typeof selector === 'string') {
557
- elements = document.querySelectorAll(selector);
558
- } else if (selector.nodeName) {
559
- elements = [selector]; // emulate a NodeList by casting a single Node as an array
560
- } else {
561
- elements = selector;
562
- }
563
-
564
- forEach(elements, function (element) {
565
- if (_this4.elements.indexOf(element) === -1) {
566
- return;
567
- }
568
-
569
- _this4.elements = _this4.elements.filter(function (el) {
570
- return el !== element;
571
- });
572
-
573
- if (_this4.instanceSelector) {
574
- element.classList.remove(_this4.instanceSelector.substr(1));
575
- }
576
-
577
- delete element.readmore;
578
- element.style.height = 'initial';
579
- element.style.maxHeight = 'initial';
580
- element.removeAttribute('data-readmore');
581
- element.removeAttribute('aria-expanded');
582
- var trigger = document.querySelector("[aria-controls=\"".concat(element.id, "\"]"));
583
-
584
- if (trigger) {
585
- trigger.remove();
586
- }
587
-
588
- if (element.id.indexOf('rmjs-') !== -1) {
589
- element.removeAttribute('id');
590
- }
591
- });
592
- delete this;
593
- }
594
- }]);
595
-
596
- return Readmore;
597
- }();
598
-
599
- Readmore.VERSION = "3.0.0-beta-1";
600
- /* harmony default export */ __webpack_exports__["default"] = (Readmore);
601
-
602
- /***/ }),
603
-
604
- /***/ 0:
605
- /*!*******************************!*\
606
- !*** multi ./src/readmore.js ***!
607
- \*******************************/
608
- /*! no static exports found */
609
- /***/ (function(module, exports, __webpack_require__) {
610
-
611
- module.exports = __webpack_require__(/*! ./src/readmore.js */"./src/readmore.js");
612
-
613
-
614
- /***/ })
615
-
616
- /******/ })["default"];
617
- });
618
- //# sourceMappingURL=readmore.js.map