jekyll-pig 0.0.2 → 0.0.5

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 (3) hide show
  1. checksums.yaml +4 -4
  2. data/lib/jekyll-pig.rb +294 -262
  3. metadata +5 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f73810e7360f4a48d45c78d83f0653beb16da0243cfb94164a6cc049a16cbe70
4
- data.tar.gz: cd92492bd2faa8766fe3b9afbed32b295cbe9deb828e30422eff3da8055fe76d
3
+ metadata.gz: bc22ff1902fb72ae001ac574bb84687afabcb815c54169d470b96dad48315ad7
4
+ data.tar.gz: d91b9e706a8a81841ec856a64870c6a5831030327e444d390bb27e92217c169d
5
5
  SHA512:
6
- metadata.gz: 342632257774fca9636fabfe4dc78866f5643075426b7c3fff2b88ffb55ca58b2f72172d98c7eb82d8e0f0b309f8cb4eac87878c7160c2b7c643dee343934ffa
7
- data.tar.gz: 227ba484c11be61757766ada3c307ed79cc3333d7d6056ba31282610d308063f2cd7958af00933fbd52bee92a1b0411dbeb4c8c007dd65823545e6a2a6d25b29
6
+ metadata.gz: e63a1cee3e5aa25416246030f113ac8271bb3e5872038ea7317c1873029cfe4d3c66b96d753d4dee6c7b22914399a3a876a10520b619fa70bb15e1f9926719e5
7
+ data.tar.gz: 38ee6decfa0bff283ee334362ea1bf2552874abeec76339b963b819b12e9bc873238a48e5a853c6fae9b6159ed1d8f07af29e1743322f6dc578197cdc8aa39d7
data/lib/jekyll-pig.rb CHANGED
@@ -1,262 +1,294 @@
1
-
2
- require 'fileutils'
3
- require 'json'
4
- require 'mini_magick'
5
-
6
- module JekyllPig
7
-
8
- class SourceGallery
9
- def initialize(path, name)
10
- @path = path
11
- @name = name
12
- end
13
- def to_s
14
- "gallery #{@name} at #{@path}"
15
- end
16
- def path
17
- @path
18
- end
19
- def name
20
- @name
21
- end
22
- end
23
-
24
- class JekyllPig < Jekyll::Generator
25
-
26
- @@image_cache = {}
27
-
28
- @@pig_min_js = '!function(t){"use strict";var i,e,s=(e=!(i=[]),{add:function(t){i.length||window.addEventListener("resize",n),i.push(t)},disable:function(){window.removeEventListener("resize",n)},reEnable:function(){window.addEventListener("resize",n)}});function n(){e||(e=!0,window.requestAnimationFrame?window.requestAnimationFrame(o):setTimeout(o,66))}function o(){i.forEach(function(t){t()}),e=!1}function a(t,i){return this.inRAF=!1,this.isTransitioning=!1,this.minAspectRatioRequiresTransition=!1,this.minAspectRatio=null,this.latestYOffset=0,this.lastWindowWidth=window.innerWidth,this.scrollDirection="down",this.visibleImages=[],this.settings={containerId:"pig",scroller:window,classPrefix:"pig",figureTagName:"figure",spaceBetweenImages:8,transitionSpeed:500,primaryImageBufferHeight:1e3,secondaryImageBufferHeight:300,thumbnailSize:20,urlForSize:function(t,i){return"/img/"+i+"/"+t},onClickHandler:function(t){},getMinAspectRatio:function(t){return t<=640?2:t<=1280?4:t<=1920?5:6},getImageSize:function(t){return t<=640?100:t<=1920?250:500}},function(t,i){for(var e in i)i.hasOwnProperty(e)&&(t[e]=i[e])}(this.settings,i||{}),this.container=document.getElementById(this.settings.containerId),this.container||console.error("Could not find element with ID "+this.settings.containerId),this.scroller=this.settings.scroller,this.images=this._parseImageData(t),function(t,i,e){var s="#"+t+" { position: relative;}."+i+"-figure { background-color: #D5D5D5; overflow: hidden; left: 0; position: absolute; top: 0; margin: 0;}."+i+"-figure img { left: 0; position: absolute; top: 0; height: 100%; width: 100%; opacity: 0; transition: "+e/1e3+"s ease opacity; -webkit-transition: "+e/1e3+"s ease opacity;}."+i+"-figure img."+i+"-thumbnail { -webkit-filter: blur(30px); filter: blur(30px); left: auto; position: relative; width: auto;}."+i+"-figure img."+i+"-loaded { opacity: 1;}",n=document.head||document.getElementsByTagName("head")[0],o=document.createElement("style");o.type="text/css",o.styleSheet?o.styleSheet.cssText=s:o.appendChild(document.createTextNode(s)),n.appendChild(o)}(this.settings.containerId,this.settings.classPrefix,this.settings.transitionSpeed),this}function r(t,i,e){return this.existsOnPage=!1,this.aspectRatio=t.aspectRatio,this.filename=t.filename,this.index=i,this.pig=e,this.classNames={figure:e.settings.classPrefix+"-figure",thumbnail:e.settings.classPrefix+"-thumbnail",loaded:e.settings.classPrefix+"-loaded"},this}a.prototype._getTransitionTimeout=function(){return 1.5*this.settings.transitionSpeed},a.prototype._getTransitionString=function(){return this.isTransitioning?this.settings.transitionSpeed/1e3+"s transform ease":"none"},a.prototype._recomputeMinAspectRatio=function(){var t=this.minAspectRatio;this.minAspectRatio=this.settings.getMinAspectRatio(this.lastWindowWidth),null!==t&&t!==this.minAspectRatio?this.minAspectRatioRequiresTransition=!0:this.minAspectRatioRequiresTransition=!1},a.prototype._parseImageData=function(t){var s=[];return t.forEach(function(t,i){var e=new r(t,i,this);s.push(e)}.bind(this)),s},a.prototype._computeLayout=function(){var s=parseInt(this.container.clientWidth),n=[],o=0,a=0,r=0;this._recomputeMinAspectRatio(),!this.isTransitioning&&this.minAspectRatioRequiresTransition&&(this.isTransitioning=!0,setTimeout(function(){this.isTransitioning=!1},this._getTransitionTimeout()));var h=this._getTransitionString();[].forEach.call(this.images,function(t,i){if(r+=parseFloat(t.aspectRatio),n.push(t),r>=this.minAspectRatio||i+1===this.images.length){r=Math.max(r,this.minAspectRatio);var e=(s-this.settings.spaceBetweenImages*(n.length-1))/r;n.forEach(function(t){var i=e*t.aspectRatio;t.style={width:parseInt(i),height:parseInt(e),translateX:o,translateY:a,transition:h},o+=i+this.settings.spaceBetweenImages}.bind(this)),n=[],r=0,a+=parseInt(e)+this.settings.spaceBetweenImages,o=0}}.bind(this)),this.totalHeight=a-this.settings.spaceBetweenImages},a.prototype._doLayout=function(){this.container.style.height=this.totalHeight+"px";var t="up"===this.scrollDirection?this.settings.primaryImageBufferHeight:this.settings.secondaryImageBufferHeight,i="down"===this.scrollDirection?this.settings.secondaryImageBufferHeight:this.settings.primaryImageBufferHeight,e=function(t){for(var i=0;isNaN(t.offsetTop)||(i+=t.offsetTop),t=t.offsetParent;);return i}(this.container),s=this.scroller===window?window.innerHeight:this.scroller.offsetHeight,n=this.latestYOffset-e-t,o=this.latestYOffset-e+s+i;this.images.forEach(function(t){t.style.translateY+t.style.height<n||t.style.translateY>o?t.hide():t.load()}.bind(this))},a.prototype._getOnScroll=function(){var i=this;return function(){var t=i.scroller===window?window.pageYOffset:i.scroller.scrollTop;i.previousYOffset=i.latestYOffset||t,i.latestYOffset=t,i.scrollDirection=i.latestYOffset>i.previousYOffset?"down":"up",i.inRAF||(i.inRAF=!0,window.requestAnimationFrame(function(){i._doLayout(),i.inRAF=!1}))}},a.prototype.enable=function(){return this.onScroll=this._getOnScroll(),this.scroller.addEventListener("scroll",this.onScroll),this.onScroll(),this._computeLayout(),this._doLayout(),s.add(function(){this.lastWindowWidth=this.scroller===window?window.innerWidth:this.scroller.offsetWidth,this._computeLayout(),this._doLayout()}.bind(this)),this},a.prototype.disable=function(){return this.scroller.removeEventListener("scroll",this.onScroll),s.disable(),this},r.prototype.load=function(){this.existsOnPage=!0,this._updateStyles(),this.pig.container.appendChild(this.getElement()),setTimeout(function(){this.existsOnPage&&(this.thumbnail||(this.thumbnail=new Image,this.thumbnail.src=this.pig.settings.urlForSize(this.filename,this.pig.settings.thumbnailSize),this.thumbnail.className=this.classNames.thumbnail,this.thumbnail.onload=function(){this.thumbnail&&(this.thumbnail.className+=" "+this.classNames.loaded)}.bind(this),this.getElement().appendChild(this.thumbnail)),this.fullImage||(this.fullImage=new Image,this.fullImage.src=this.pig.settings.urlForSize(this.filename,this.pig.settings.getImageSize(this.pig.lastWindowWidth)),this.fullImage.onload=function(){this.fullImage&&(this.fullImage.className+=" "+this.classNames.loaded)}.bind(this),this.getElement().appendChild(this.fullImage)))}.bind(this),100)},r.prototype.hide=function(){this.getElement()&&(this.thumbnail&&(this.thumbnail.src="",this.getElement().removeChild(this.thumbnail),delete this.thumbnail),this.fullImage&&(this.fullImage.src="",this.getElement().removeChild(this.fullImage),delete this.fullImage)),this.existsOnPage&&this.pig.container.removeChild(this.getElement()),this.existsOnPage=!1},r.prototype.getElement=function(){return this.element||(this.element=document.createElement(this.pig.settings.figureTagName),this.element.className=this.classNames.figure,this.element.addEventListener("click",function(){this.pig.settings.onClickHandler(this.filename)}.bind(this)),this._updateStyles()),this.element},r.prototype._updateStyles=function(){this.getElement().style.transition=this.style.transition,this.getElement().style.width=this.style.width+"px",this.getElement().style.height=this.style.height+"px",this.getElement().style.transform="translate3d("+this.style.translateX+"px,"+this.style.translateY+"px, 0)"},"function"==typeof define&&define.amd?define([],function(){return a}):"undefined"!=typeof module&&module.exports?module.exports=a:t.Pig=a}("undefined"!=typeof window?window:this);'
29
-
30
- def full_size_html(gallery_name, name, date, prev_url, next_url)
31
- "---\n" \
32
- "layout: post\n" \
33
- "title: #{name}\n" \
34
- "date: #{date.strftime("%Y-%m-%d %H:%M:%S")}\n" \
35
- "permalink: /assets/html/#{gallery_name}/#{name}.html\n" \
36
- "exclude: true\n" \
37
- "---\n" \
38
- "<div><a href=\"#{prev_url}\" style=\"display:inline;\">prev</a><a href=\"#{next_url}\" style=\"display:inline; float:right\">next</a></div>\n" \
39
- "<img src=\"{{site.baseurl}}/assets/img/#{gallery_name}/1024/#{name}\"/>\n"
40
- end
41
-
42
- def gallery_html(id, image_data)
43
- "<div id='#{id}_pig'></div>\n" \
44
- "<script src='{{site.baseurl}}/assets/js/pig.min.js'></script>\n" \
45
- "<script>\n" \
46
- "var #{id}_pig = new Pig(\n" \
47
- " #{image_data.to_json()},\n" \
48
- " {\n" \
49
- " containerId: '#{id}_pig',\n" \
50
- " classPrefix: '#{id}_pig',\n" \
51
- " urlForSize: function(filename, size) {\n" \
52
- " return '{{site.baseurl}}/assets/img/#{id}/' + size + '/' + filename;\n" \
53
- " },\n" \
54
- " onClickHandler: function(filename) {\n" \
55
- " window.location.href = '{{site.baseurl}}/assets/html/#{id}/' + filename + '.html';\n" \
56
- " }\n" \
57
- " }\n" \
58
- ").enable();\n" \
59
- "</script>"
60
- end
61
-
62
- def image_html_url(gallery_name, image_name)
63
- "/assets/html/#{gallery_name}/#{image_name}.html"
64
- end
65
-
66
- #read the image data from the _includes folder
67
- def get_image_data(gallery_name)
68
- image_data = []
69
- #read image_data if existing
70
- if File.exists?(File.join(@data_path, "#{gallery_name}.json"))
71
- File.open(File.join(@data_path, "#{gallery_name}.json"), 'r') { |file|
72
- #get array of image data (drop 'var imageData = ' and ';')
73
- image_data = JSON.parse(file.read)
74
- }
75
- end
76
- image_data
77
- end
78
-
79
- #read images that require processing from gallery
80
- def get_images(gallery_path)
81
- patterns = ['*.jpg', '*.jpeg', '*.png'].map { |ext| File.join(gallery_path, ext) }
82
- Dir.glob(patterns).map { |path| File.basename(path) }
83
- end
84
-
85
- def get_image(gallery_path, image_name)
86
- image = @@image_cache[File.join(gallery_path, image_name)]
87
- if image == nil
88
- image = MiniMagick::Image.open(File.join(gallery_path, image_name))
89
- @@image_cache[File.join(gallery_path, image_name)] = image
90
- end
91
- image
92
- end
93
-
94
- def get_image_date(gallery_path, image_name)
95
- image_date = nil
96
- begin
97
- image = get_image(gallery_path, image_name)
98
- exif_date = image.exif['DateTimeOriginal']
99
- if exif_date == nil
100
- #no exif date, try to get from file name
101
- image_date = Time.strptime(image_name, "%Y-%m-%d")
102
- else
103
- #try to get the image date from exif
104
- image_date = Time.strptime(exif_date, "%Y:%m:%d %H:%M:%S")
105
- end
106
- rescue
107
- #get the date from file if possible
108
- image_date = File.mtime(File.join(gallery_path, image_name))
109
- end
110
- image_date
111
- end
112
-
113
- def get_previous_url(image_data, gallery_name, image_name)
114
- index = image_data.index { |data| data['filename'] == image_name }
115
- index = index - 1
116
- if index < 0
117
- index = image_data.length - 1
118
- end
119
- image_html_url(gallery_name, image_data[index]['filename'])
120
- end
121
-
122
- def get_next_url(image_data, gallery_name, image_name)
123
- index = image_data.index { |data| data['filename'] == image_name }
124
- index = index + 1
125
- if index >= image_data.length
126
- index = 0
127
- end
128
- image_html_url(gallery_name, image_data[index]['filename'])
129
- end
130
-
131
- #create thumbnails and fullsize image assets, and create full size html page for a given image
132
- def process_image(image_data, gallery_id, gallery_path, image_name)
133
- #puts "jekyll-pig: processing " << image_name
134
- #create thumbs
135
- [1024, 500, 250, 100, 20].each { |size|
136
- size_out_path = File.join(@img_path, gallery_id, size.to_s)
137
- resized_img_path = File.join(size_out_path, image_name)
138
- if not File.exists? resized_img_path
139
- image = get_image(gallery_path, image_name)
140
- image.resize("x" + size.to_s)
141
- FileUtils.mkdir_p size_out_path unless File.exists? size_out_path
142
- image.write(resized_img_path)
143
- end
144
- }
145
- full_size_html_path = File.join(@html_path, gallery_id, image_name + ".html")
146
- #create full size html if it doesn't exist
147
- if not File.exists? full_size_html_path
148
- #get image date
149
- image_date = get_image_date(gallery_path, image_name)
150
- #create full size html text
151
- full_size_html = full_size_html(gallery_id, image_name, image_date,
152
- get_previous_url(image_data, gallery_id, image_name),
153
- get_next_url(image_data, gallery_id, image_name))
154
- File.open(full_size_html_path, 'w') { |file|
155
- file.write(full_size_html)
156
- }
157
- end
158
- end
159
-
160
- def get_paths
161
- @assets_path = File.join(@site.source, "assets")
162
- @js_path = File.join(@assets_path, "js")
163
- @data_path = File.join(@site.source, "_data")
164
- @img_path = File.join(@assets_path, "img")
165
- @html_path = File.join(@assets_path, "html")
166
- @includes_path = File.join(@site.source, "_includes")
167
- end
168
-
169
- def get_galleries
170
- galleries = []
171
- config_galleries = Jekyll.configuration({})['galleries']
172
- if config_galleries != nil
173
- config_galleries.each do |gallery|
174
- full_path = File.join(@site.source, gallery['path'])
175
- if File.directory?(full_path)
176
- galleries << SourceGallery.new(full_path, gallery['name'])
177
- end
178
- end
179
- else
180
- default_gallery_path = File.join(@site.source, 'gallery')
181
- if File.directory?(default_gallery_path)
182
- galleries << SourceGallery.new(default_gallery_path, 'gallery')
183
- end
184
- end
185
- galleries
186
- end
187
-
188
- def make_output_paths
189
- FileUtils.mkdir_p @assets_path unless File.exists? @assets_path
190
- FileUtils.mkdir_p @js_path unless File.exists? @js_path
191
- FileUtils.mkdir_p @img_path unless File.exists? @img_path
192
- FileUtils.mkdir_p @html_path unless File.exists? @html_path
193
- FileUtils.mkdir_p @includes_path unless File.exists? @includes_path
194
- FileUtils.mkdir_p @data_path unless File.exists? @data_path
195
- end
196
-
197
- def augment_image_data(gallery, image_data, images)
198
- images.each do |image_name|
199
- #append data to image_data array if it's not already there
200
- if not image_data.any? { |data| data['filename'] == image_name }
201
- #get image date
202
- image_date = get_image_date(gallery.path, image_name)
203
- image = get_image(gallery.path, image_name)
204
- image_data <<
205
- {
206
- 'datetime' => image_date.to_s,
207
- 'filename' => image_name,
208
- 'aspectRatio' => image.width.to_f / image.height
209
- }
210
- end
211
- end
212
- end
213
-
214
- def generate(site)
215
- @site = site
216
- get_paths()
217
- make_output_paths()
218
- galleries = get_galleries()
219
- galleries.each do |gallery|
220
-
221
- #make gallery specific html and image output paths
222
- html_output_path = File.join(@html_path, gallery.name)
223
- FileUtils.mkdir_p html_output_path unless File.exists? html_output_path
224
- img_output_path = File.join(@img_path, gallery.name)
225
- FileUtils.mkdir_p img_output_path unless File.exists? img_output_path
226
-
227
- #write pig.min.js to js path
228
- if not File.exists? File.join(@js_path, 'pig.min.js')
229
- File.open(File.join(@js_path, 'pig.min.js'), 'w') { |file| file.write(@@pig_min_js) }
230
- end
231
-
232
- #get image data from _data
233
- image_data = get_image_data(gallery.name)
234
-
235
- #get images from gallery
236
- images = get_images(gallery.path)
237
-
238
- #add any additional images to image_data
239
- augment_image_data(gallery, image_data, images)
240
-
241
- #sort image data
242
- image_data = image_data.sort_by { |data| data['datetime'] }
243
-
244
- #process images
245
- images.each do |image_name|
246
- #create thumbs, full size, and html assets for each image
247
- process_image(image_data, gallery.name, gallery.path, image_name)
248
- end
249
-
250
- #write image_data
251
- File.open(File.join(@data_path, "#{gallery.name}.json"), 'w') { |file|
252
- file.write(image_data.to_json)
253
- }
254
-
255
- #save this gallery's includable content
256
- File.open(File.join(@includes_path, "#{gallery.name}.html"), 'w') { |file|
257
- file.write(gallery_html(gallery.name, image_data))
258
- }
259
- end
260
- end
261
- end
262
- end
1
+
2
+ require 'fileutils'
3
+ require 'json'
4
+ require 'mini_magick'
5
+
6
+ module JekyllPig
7
+
8
+ class SourceGallery
9
+ def initialize(path, name)
10
+ @path = path
11
+ @name = name
12
+ end
13
+ def to_s
14
+ "gallery #{@name} at #{@path}"
15
+ end
16
+ def path
17
+ @path
18
+ end
19
+ def name
20
+ @name
21
+ end
22
+ end
23
+
24
+ class JekyllPig < Jekyll::Generator
25
+
26
+ @@image_cache = {}
27
+
28
+ @@pig_min_js = '!function(t){"use strict";var i,e,s=(e=!(i=[]),{add:function(t){i.length||window.addEventListener("resize",n),i.push(t)},disable:function(){window.removeEventListener("resize",n)},reEnable:function(){window.addEventListener("resize",n)}});function n(){e||(e=!0,window.requestAnimationFrame?window.requestAnimationFrame(o):setTimeout(o,66))}function o(){i.forEach(function(t){t()}),e=!1}function a(t,i){return this.inRAF=!1,this.isTransitioning=!1,this.minAspectRatioRequiresTransition=!1,this.minAspectRatio=null,this.latestYOffset=0,this.lastWindowWidth=window.innerWidth,this.scrollDirection="down",this.visibleImages=[],this.settings={containerId:"pig",scroller:window,classPrefix:"pig",figureTagName:"figure",spaceBetweenImages:8,transitionSpeed:500,primaryImageBufferHeight:1e3,secondaryImageBufferHeight:300,thumbnailSize:20,urlForSize:function(t,i){return"/img/"+i+"/"+t},onClickHandler:function(t){},getMinAspectRatio:function(t){return t<=640?2:t<=1280?4:t<=1920?5:6},getImageSize:function(t){return t<=640?100:t<=1920?250:500}},function(t,i){for(var e in i)i.hasOwnProperty(e)&&(t[e]=i[e])}(this.settings,i||{}),this.container=document.getElementById(this.settings.containerId),this.container||console.error("Could not find element with ID "+this.settings.containerId),this.scroller=this.settings.scroller,this.images=this._parseImageData(t),function(t,i,e){var s="#"+t+" { position: relative;}."+i+"-figure { background-color: #D5D5D5; overflow: hidden; left: 0; position: absolute; top: 0; margin: 0;}."+i+"-figure img { left: 0; position: absolute; top: 0; height: 100%; width: 100%; opacity: 0; transition: "+e/1e3+"s ease opacity; -webkit-transition: "+e/1e3+"s ease opacity;}."+i+"-figure img."+i+"-thumbnail { -webkit-filter: blur(30px); filter: blur(30px); left: auto; position: relative; width: auto;}."+i+"-figure img."+i+"-loaded { opacity: 1;}",n=document.head||document.getElementsByTagName("head")[0],o=document.createElement("style");o.type="text/css",o.styleSheet?o.styleSheet.cssText=s:o.appendChild(document.createTextNode(s)),n.appendChild(o)}(this.settings.containerId,this.settings.classPrefix,this.settings.transitionSpeed),this}function r(t,i,e){return this.existsOnPage=!1,this.aspectRatio=t.aspectRatio,this.filename=t.filename,this.index=i,this.pig=e,this.classNames={figure:e.settings.classPrefix+"-figure",thumbnail:e.settings.classPrefix+"-thumbnail",loaded:e.settings.classPrefix+"-loaded"},this}a.prototype._getTransitionTimeout=function(){return 1.5*this.settings.transitionSpeed},a.prototype._getTransitionString=function(){return this.isTransitioning?this.settings.transitionSpeed/1e3+"s transform ease":"none"},a.prototype._recomputeMinAspectRatio=function(){var t=this.minAspectRatio;this.minAspectRatio=this.settings.getMinAspectRatio(this.lastWindowWidth),null!==t&&t!==this.minAspectRatio?this.minAspectRatioRequiresTransition=!0:this.minAspectRatioRequiresTransition=!1},a.prototype._parseImageData=function(t){var s=[];return t.forEach(function(t,i){var e=new r(t,i,this);s.push(e)}.bind(this)),s},a.prototype._computeLayout=function(){var s=parseInt(this.container.clientWidth),n=[],o=0,a=0,r=0;this._recomputeMinAspectRatio(),!this.isTransitioning&&this.minAspectRatioRequiresTransition&&(this.isTransitioning=!0,setTimeout(function(){this.isTransitioning=!1},this._getTransitionTimeout()));var h=this._getTransitionString();[].forEach.call(this.images,function(t,i){if(r+=parseFloat(t.aspectRatio),n.push(t),r>=this.minAspectRatio||i+1===this.images.length){r=Math.max(r,this.minAspectRatio);var e=(s-this.settings.spaceBetweenImages*(n.length-1))/r;n.forEach(function(t){var i=e*t.aspectRatio;t.style={width:parseInt(i),height:parseInt(e),translateX:o,translateY:a,transition:h},o+=i+this.settings.spaceBetweenImages}.bind(this)),n=[],r=0,a+=parseInt(e)+this.settings.spaceBetweenImages,o=0}}.bind(this)),this.totalHeight=a-this.settings.spaceBetweenImages},a.prototype._doLayout=function(){this.container.style.height=this.totalHeight+"px";var t="up"===this.scrollDirection?this.settings.primaryImageBufferHeight:this.settings.secondaryImageBufferHeight,i="down"===this.scrollDirection?this.settings.secondaryImageBufferHeight:this.settings.primaryImageBufferHeight,e=function(t){for(var i=0;isNaN(t.offsetTop)||(i+=t.offsetTop),t=t.offsetParent;);return i}(this.container),s=this.scroller===window?window.innerHeight:this.scroller.offsetHeight,n=this.latestYOffset-e-t,o=this.latestYOffset-e+s+i;this.images.forEach(function(t){t.style.translateY+t.style.height<n||t.style.translateY>o?t.hide():t.load()}.bind(this))},a.prototype._getOnScroll=function(){var i=this;return function(){var t=i.scroller===window?window.pageYOffset:i.scroller.scrollTop;i.previousYOffset=i.latestYOffset||t,i.latestYOffset=t,i.scrollDirection=i.latestYOffset>i.previousYOffset?"down":"up",i.inRAF||(i.inRAF=!0,window.requestAnimationFrame(function(){i._doLayout(),i.inRAF=!1}))}},a.prototype.enable=function(){return this.onScroll=this._getOnScroll(),this.scroller.addEventListener("scroll",this.onScroll),this.onScroll(),this._computeLayout(),this._doLayout(),s.add(function(){this.lastWindowWidth=this.scroller===window?window.innerWidth:this.scroller.offsetWidth,this._computeLayout(),this._doLayout()}.bind(this)),this},a.prototype.disable=function(){return this.scroller.removeEventListener("scroll",this.onScroll),s.disable(),this},r.prototype.load=function(){this.existsOnPage=!0,this._updateStyles(),this.pig.container.appendChild(this.getElement()),setTimeout(function(){this.existsOnPage&&(this.thumbnail||(this.thumbnail=new Image,this.thumbnail.src=this.pig.settings.urlForSize(this.filename,this.pig.settings.thumbnailSize),this.thumbnail.className=this.classNames.thumbnail,this.thumbnail.onload=function(){this.thumbnail&&(this.thumbnail.className+=" "+this.classNames.loaded)}.bind(this),this.getElement().appendChild(this.thumbnail)),this.fullImage||(this.fullImage=new Image,this.fullImage.src=this.pig.settings.urlForSize(this.filename,this.pig.settings.getImageSize(this.pig.lastWindowWidth)),this.fullImage.onload=function(){this.fullImage&&(this.fullImage.className+=" "+this.classNames.loaded)}.bind(this),this.getElement().appendChild(this.fullImage)))}.bind(this),100)},r.prototype.hide=function(){this.getElement()&&(this.thumbnail&&(this.thumbnail.src="",this.getElement().removeChild(this.thumbnail),delete this.thumbnail),this.fullImage&&(this.fullImage.src="",this.getElement().removeChild(this.fullImage),delete this.fullImage)),this.existsOnPage&&this.pig.container.removeChild(this.getElement()),this.existsOnPage=!1},r.prototype.getElement=function(){return this.element||(this.element=document.createElement(this.pig.settings.figureTagName),this.element.className=this.classNames.figure,this.element.addEventListener("click",function(){this.pig.settings.onClickHandler(this.filename)}.bind(this)),this._updateStyles()),this.element},r.prototype._updateStyles=function(){this.getElement().style.transition=this.style.transition,this.getElement().style.width=this.style.width+"px",this.getElement().style.height=this.style.height+"px",this.getElement().style.transform="translate3d("+this.style.translateX+"px,"+this.style.translateY+"px, 0)"},"function"==typeof define&&define.amd?define([],function(){return a}):"undefined"!=typeof module&&module.exports?module.exports=a:t.Pig=a}("undefined"!=typeof window?window:this);'
29
+
30
+ def full_size_html(gallery_name, name, date, prev_url, next_url)
31
+ "---\n" \
32
+ "layout: post\n" \
33
+ "title: #{name}\n" \
34
+ "date: #{date.strftime("%Y-%m-%d %H:%M:%S")}\n" \
35
+ "permalink: /assets/html/#{gallery_name}/#{name}.html\n" \
36
+ "exclude: true\n" \
37
+ "---\n" \
38
+ "<div><a href=\"#{prev_url}\" style=\"display:inline;\">prev</a><a href=\"#{next_url}\" style=\"display:inline; float:right\">next</a></div>\n" \
39
+ "<img src=\"{{site.baseurl}}/assets/img/#{gallery_name}/1024/#{name}\"/>\n"
40
+ end
41
+
42
+ def gallery_html(id, image_data)
43
+ "<div id='#{id}_pig'></div>\n" \
44
+ "<script src='{{site.baseurl}}/assets/js/pig.min.js'></script>\n" \
45
+ "<script>\n" \
46
+ "var #{id}_pig = new Pig(\n" \
47
+ " #{image_data.to_json()},\n" \
48
+ " {\n" \
49
+ " containerId: '#{id}_pig',\n" \
50
+ " classPrefix: '#{id}_pig',\n" \
51
+ " urlForSize: function(filename, size) {\n" \
52
+ " return '{{site.baseurl}}/assets/img/#{id}/' + size + '/' + filename;\n" \
53
+ " },\n" \
54
+ " onClickHandler: function(filename) {\n" \
55
+ " window.location.href = '{{site.baseurl}}/assets/html/#{id}/' + filename + '.html';\n" \
56
+ " }\n" \
57
+ " }\n" \
58
+ ").enable();\n" \
59
+ "</script>"
60
+ end
61
+
62
+ def image_html_url(gallery_name, image_name)
63
+ "/assets/html/#{gallery_name}/#{image_name}.html"
64
+ end
65
+
66
+ #read the image data from the _includes folder
67
+ def get_image_data(gallery_name)
68
+ image_data = []
69
+ #read image_data if existing
70
+ if File.exists?(File.join(@data_path, "#{gallery_name}.json"))
71
+ File.open(File.join(@data_path, "#{gallery_name}.json"), 'r') { |file|
72
+ #get array of image data (drop 'var imageData = ' and ';')
73
+ image_data = JSON.parse(file.read)
74
+ }
75
+ end
76
+ image_data
77
+ end
78
+
79
+ #get a list of image file names from a given path
80
+ def get_images(path)
81
+ patterns = ['*.jpg', '*.jpeg', '*.png'].map { |ext| File.join(path, ext) }
82
+ Dir.glob(patterns).map { |filepath| File.basename(filepath) }
83
+ end
84
+
85
+ def get_image(gallery_path, image_name)
86
+ image = @@image_cache[File.join(gallery_path, image_name)]
87
+ if image == nil
88
+ image = MiniMagick::Image.open(File.join(gallery_path, image_name))
89
+ @@image_cache[File.join(gallery_path, image_name)] = image
90
+ end
91
+ image
92
+ end
93
+
94
+ def get_image_date(gallery_path, image_name)
95
+ image_date = nil
96
+ begin
97
+ image = get_image(gallery_path, image_name)
98
+ exif_date = image.exif['DateTimeOriginal']
99
+ if exif_date == nil
100
+ #no exif date, try to get from file name
101
+ image_date = Time.strptime(image_name, "%Y-%m-%d")
102
+ else
103
+ #try to get the image date from exif
104
+ image_date = Time.strptime(exif_date, "%Y:%m:%d %H:%M:%S")
105
+ end
106
+ rescue
107
+ #get the date from file if possible
108
+ image_date = File.mtime(File.join(gallery_path, image_name))
109
+ end
110
+ image_date
111
+ end
112
+
113
+ def get_previous_url(image_data, gallery_name, image_name)
114
+ index = image_data.index { |data| data['filename'] == image_name }
115
+ index = index - 1
116
+ if index < 0
117
+ index = image_data.length - 1
118
+ end
119
+ image_html_url(gallery_name, image_data[index]['filename'])
120
+ end
121
+
122
+ def get_next_url(image_data, gallery_name, image_name)
123
+ index = image_data.index { |data| data['filename'] == image_name }
124
+ index = index + 1
125
+ if index >= image_data.length
126
+ index = 0
127
+ end
128
+ image_html_url(gallery_name, image_data[index]['filename'])
129
+ end
130
+
131
+ #create thumbnails and fullsize image assets
132
+ def process_images(image_data, gallery_id, gallery_path, images)
133
+ #create thumbs
134
+ sizes = [1024, 500, 250, 100, 20]
135
+ sizes.each { |size|
136
+ #output path for current size
137
+ size_out_path = File.join(@img_path, gallery_id, size.to_s)
138
+ FileUtils.mkdir_p size_out_path unless File.exists? size_out_path
139
+
140
+ #images that have already been processed for the current size
141
+ done_images = get_images(size_out_path)
142
+ #all images in the gallery with the ones already done taken away
143
+ todo_images = images - done_images
144
+
145
+ #function to get the source path to use for creating the given size thumbnail
146
+ #i.e. use the 500px sized images to make the 250px versions
147
+ source_for_size = -> (size) {
148
+ index = sizes.index(size)
149
+ source = gallery_path
150
+ if index != nil && index != 0
151
+ source = File.join(@img_path, gallery_id, sizes[index - 1].to_s)
152
+ end
153
+ source
154
+ }
155
+
156
+ #do the processing in a batch
157
+ mog = MiniMagick::Tool::Mogrify.new
158
+ mog.resize("x#{size}")
159
+ mog.sampling_factor('4:2:0')
160
+ mog.interlace('Plane')
161
+ mog.strip()
162
+ mog.quality('75')
163
+ mog.path(size_out_path)
164
+ source_path = source_for_size.call(size)
165
+ todo_images.each { |todo| mog << File.join(source_path, todo) }
166
+ mog.call
167
+ }
168
+ end
169
+
170
+ #create full size html page for a given image
171
+ def process_image(image_data, gallery_id, gallery_path, image_name)
172
+ full_size_html_path = File.join(@html_path, gallery_id, image_name + ".html")
173
+ #create full size html if it doesn't exist
174
+ if not File.exists? full_size_html_path
175
+ #get image date
176
+ image_date = get_image_date(gallery_path, image_name)
177
+ #create full size html text
178
+ full_size_html = full_size_html(gallery_id, image_name, image_date,
179
+ get_previous_url(image_data, gallery_id, image_name),
180
+ get_next_url(image_data, gallery_id, image_name))
181
+ File.open(full_size_html_path, 'w') { |file|
182
+ file.write(full_size_html)
183
+ }
184
+ end
185
+ end
186
+
187
+ def get_paths
188
+ @assets_path = File.join(@site.source, "assets")
189
+ @js_path = File.join(@assets_path, "js")
190
+ @data_path = File.join(@site.source, "_data")
191
+ @img_path = File.join(@assets_path, "img")
192
+ @html_path = File.join(@assets_path, "html")
193
+ @includes_path = File.join(@site.source, "_includes")
194
+ end
195
+
196
+ def get_galleries
197
+ galleries = []
198
+ config_galleries = Jekyll.configuration({})['galleries']
199
+ if config_galleries != nil
200
+ config_galleries.each do |gallery|
201
+ full_path = File.join(@site.source, gallery['path'])
202
+ if File.directory?(full_path)
203
+ galleries << SourceGallery.new(full_path, gallery['name'])
204
+ end
205
+ end
206
+ else
207
+ default_gallery_path = File.join(@site.source, 'gallery')
208
+ if File.directory?(default_gallery_path)
209
+ galleries << SourceGallery.new(default_gallery_path, 'gallery')
210
+ end
211
+ end
212
+ galleries
213
+ end
214
+
215
+ def make_output_paths
216
+ FileUtils.mkdir_p @assets_path unless File.exists? @assets_path
217
+ FileUtils.mkdir_p @js_path unless File.exists? @js_path
218
+ FileUtils.mkdir_p @img_path unless File.exists? @img_path
219
+ FileUtils.mkdir_p @html_path unless File.exists? @html_path
220
+ FileUtils.mkdir_p @includes_path unless File.exists? @includes_path
221
+ FileUtils.mkdir_p @data_path unless File.exists? @data_path
222
+ end
223
+
224
+ def augment_image_data(gallery, image_data, images)
225
+ images.each do |image_name|
226
+ #append data to image_data array if it's not already there
227
+ if not image_data.any? { |data| data['filename'] == image_name }
228
+ #get image date
229
+ image_date = get_image_date(gallery.path, image_name)
230
+ image = get_image(gallery.path, image_name)
231
+ image_data <<
232
+ {
233
+ 'datetime' => image_date.to_s,
234
+ 'filename' => image_name,
235
+ 'aspectRatio' => image.width.to_f / image.height
236
+ }
237
+ end
238
+ end
239
+ end
240
+
241
+ def generate(site)
242
+ @site = site
243
+ get_paths()
244
+ make_output_paths()
245
+ galleries = get_galleries()
246
+ galleries.each do |gallery|
247
+
248
+ #make gallery specific html and image output paths
249
+ html_output_path = File.join(@html_path, gallery.name)
250
+ FileUtils.mkdir_p html_output_path unless File.exists? html_output_path
251
+ img_output_path = File.join(@img_path, gallery.name)
252
+ FileUtils.mkdir_p img_output_path unless File.exists? img_output_path
253
+
254
+ #write pig.min.js to js path
255
+ if not File.exists? File.join(@js_path, 'pig.min.js')
256
+ File.open(File.join(@js_path, 'pig.min.js'), 'w') { |file| file.write(@@pig_min_js) }
257
+ end
258
+
259
+ #get image data from _data
260
+ image_data = get_image_data(gallery.name)
261
+ old_image_data = image_data.clone
262
+
263
+ #get images from gallery
264
+ images = get_images(gallery.path)
265
+
266
+ #add any additional images to image_data
267
+ augment_image_data(gallery, image_data, images)
268
+
269
+ #sort image data
270
+ image_data = image_data.sort_by { |data| data['datetime'] }
271
+
272
+ #create thumbs
273
+ process_images(image_data, gallery.name, gallery.path, images)
274
+
275
+ images.each do |image_name|
276
+ #create html assets for each image
277
+ process_image(image_data, gallery.name, gallery.path, image_name)
278
+ end
279
+
280
+ if image_data != old_image_data
281
+ #write image_data
282
+ File.open(File.join(@data_path, "#{gallery.name}.json"), 'w') { |file|
283
+ file.write(image_data.to_json)
284
+ }
285
+
286
+ #save this gallery's includable content
287
+ File.open(File.join(@includes_path, "#{gallery.name}.html"), 'w') { |file|
288
+ file.write(gallery_html(gallery.name, image_data))
289
+ }
290
+ end
291
+ end
292
+ end
293
+ end
294
+ end
metadata CHANGED
@@ -1,11 +1,11 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jekyll-pig
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Colin Holzman
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
  date: 2020-03-04 00:00:00.000000000 Z
@@ -36,7 +36,7 @@ homepage: https://github.com/clnhlzmn/jekyll-pig
36
36
  licenses:
37
37
  - MIT
38
38
  metadata: {}
39
- post_install_message:
39
+ post_install_message:
40
40
  rdoc_options: []
41
41
  require_paths:
42
42
  - lib
@@ -52,9 +52,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
52
52
  version: '0'
53
53
  requirements:
54
54
  - ImageMagick or GraphicsMagick
55
- rubyforge_project:
56
- rubygems_version: 2.7.6
57
- signing_key:
55
+ rubygems_version: 3.1.2
56
+ signing_key:
58
57
  specification_version: 4
59
58
  summary: Jekyll image gallery generator
60
59
  test_files: []