Skip to content

Commit f8d58bb

Browse files
committed
srcset + links
1 parent c1f479f commit f8d58bb

File tree

5 files changed

+139
-43
lines changed

5 files changed

+139
-43
lines changed

README.md

+59-12
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,13 @@
22

33
This is a [Hexo](https://hexo.io) tag plugin which allows you to embed [Flickr](https://flickr.com) photo on your blog posts.
44

5+
## Features
6+
7+
* Embed your pictures in all available sizes, from 75px to 6144px
8+
* Support **srcset** HTML attribute. See https://flaviocopes.com/html-responsive-images-srcset/
9+
* Link to your image on flickr
10+
* Reference images using **live.staticflicrk.com** domain
11+
* Support caching calls to flickr API
512

613
## Installation
714

@@ -11,19 +18,34 @@ Run the following command in the root directory of hexo:
1118
npm i hexo-tag-flickr --save
1219
```
1320

21+
**Note: this is a fork from the original hexo-tag-flickr. Not published yet. PR not done either**
22+
**To use it, you must include it in your package.json like this:**
23+
24+
```
25+
"hexo-tag-flickr": "github:tomap/hexo-tag-flickr",
26+
```
27+
1428
Then add this plugin and Flickr API key in your `_config.yml`.
1529

1630
```
1731
flickr:
1832
# Flickr API key
1933
api_key: <Your API key>
2034
21-
# default size (if not specified)
35+
# default size (if none specified in the tag)
2236
default_size: -
37+
# see below for the list of supported sizes
2338
24-
# Enable Cache file
25-
cache_file_path: hexo-tag-flickr-cache.json
26-
cache_expires: 2592000000
39+
# Use srcset attribute to allow browser to download only the most relevant image size
40+
use_srcset: true
41+
42+
# insert the image inside a link to the source image on flickr to comply with flickr TOS
43+
linkto_source: true
44+
45+
# Enable Cache file (default is empty. Specify a file name to enable caching)
46+
cache_file_path:
47+
# defaults to 24h to comply with flickr TOS
48+
cache_expires: 86400000
2749
```
2850
Get your [Flickr API Key here.](https://www.flickr.com/services/api/keys/)
2951

@@ -36,14 +58,37 @@ Get your [Flickr API Key here.](https://www.flickr.com/services/api/keys/)
3658
Example:
3759

3860
```
39-
{% flickr 11909477254 %}
61+
{% flickr 32865582372 %}
62+
```
63+
64+
Will output the HTML:
65+
66+
```
67+
<a href="https://flic.kr/p/S5dGBW/sizes/l" target="_blank" rel="noopener noreferrer">
68+
<img src="https://live.staticflickr.com/505/32865582372_504939cc58_b.jpg" width="1024"
69+
srcset="https://live.staticflickr.com/505/32865582372_504939cc58_s.jpg 75w,
70+
https://live.staticflickr.com/505/32865582372_504939cc58_q.jpg 150w,
71+
https://live.staticflickr.com/505/32865582372_504939cc58_t.jpg 100w,
72+
https://live.staticflickr.com/505/32865582372_504939cc58_m.jpg 240w,
73+
https://live.staticflickr.com/505/32865582372_504939cc58_n.jpg 320w,
74+
https://live.staticflickr.com/505/32865582372_504939cc58_w.jpg 400w,
75+
https://live.staticflickr.com/505/32865582372_504939cc58.jpg 500w,
76+
https://live.staticflickr.com/505/32865582372_504939cc58_z.jpg 640w,
77+
https://live.staticflickr.com/505/32865582372_504939cc58_c.jpg 800w,
78+
https://live.staticflickr.com/505/32865582372_504939cc58_b.jpg 1024w">
79+
</a>
80+
```
81+
82+
If you disable srcset (**use_srcset: false**) and links (**linkto_source: false**)
83+
84+
```
4085
{% flickr photo 9528576237 z %}
86+
4187
```
4288

4389
Will output the HTML:
4490

4591
```
46-
<img src="https://live.staticflickr.com/3731/11909477254_1992af78e4.jpg" width="500">
4792
<img src="https://live.staticflickr.com/5445/9528576237_b87fc8f98b_z.jpg" width="640" class="photo">
4893
```
4994

@@ -67,7 +112,7 @@ photos: [
67112
]
68113
```
69114

70-
## Available size:
115+
## Available sizes:
71116

72117
* `s` small square 75x75
73118
* `q` large square 150x150
@@ -79,15 +124,17 @@ photos: [
79124
* `z` medium 640, 640 on longest side
80125
* `c` medium 800, 800 on longest side
81126
* `b` large, 1024 on longest side
82-
* `h` large, 1600 on longest side
83-
* `k` large, 2048 on longest side
127+
* `h` large, 1600 on longest side ; photo owner can restrict
128+
* `k` large, 2048 on longest side ; photo owner can restrict
129+
* `3` extra large, 3072 on longest side ; photo owner can restrict ; might only be available to PRO accounts
130+
* `4k` extra large, 4096 on longest side ; photo owner can restrict ; might only be available to PRO accounts
131+
* `f` extra large, 4096 on longest side ; photo owner can restrict ; only exists for 2:1 aspect ratio photos
132+
* `5k` extra large, 5120 on longest side ; photo owner can restrict ; might only be available to PRO accounts
133+
* `6k` extra large, 6144 on longest side ; photo owner can restrict ; might only be available to PRO accounts
84134
* `o` original image, either a jpg, gif or png, depending on source format
85135

86136
Learn more about [size suffixes](https://www.flickr.com/services/api/misc.urls.html) defined by Flickr.
87137

88-
## Note:
89-
This plugin is without Flickr authentication, it show only your public photos.
90-
91138
## Contribution
92139

93140
Run ```npm i && npm test``` to install dependencies & test the plugin (with Mocha tests)

flickrTagUtil.js

+34-9
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@
22
'use strict';
33

44
const rPhotoId = /\d{5,}/;
5-
const rPhotoSize = /^[sqtmnwzcbhko-]$/;
5+
const rPhotoSize = /^([sqtmnwzcbhkfo-]|3k|4k|5k|6k)$/;
66

77
const flickrTagUtil = {
8-
convertAttr: function(args, defaultSize) {
8+
convertAttr: function(args, defaultSize, useSrcset) {
99
const attrs = {
1010
classes: [],
1111
id: '',
1212
size: defaultSize,
13-
isWithLink: false
13+
useSrcset: useSrcset
1414
};
1515

1616
let i = 0;
@@ -40,10 +40,12 @@ const flickrTagUtil = {
4040
imgFormat: function(tag, jsonData) {
4141

4242
const imgAttr = {};
43-
44-
imgAttr.src = jsonData.source;
45-
imgAttr.width = jsonData.width;
46-
43+
imgAttr.photoId = tag.id;
44+
imgAttr.src = jsonData.selectedSize.source;
45+
imgAttr.width = jsonData.selectedSize.width;
46+
if (tag.useSrcset) {
47+
imgAttr.srcset = jsonData.sizeList.map(e => e.source + ' ' + e.width + 'w').join(', ');
48+
}
4749
imgAttr.class = tag.classes.join(' ');
4850

4951
return imgAttr;
@@ -65,18 +67,41 @@ const flickrTagUtil = {
6567
'b': 'Large',
6668
'h': 'Large 1600',
6769
'k': 'Large 2048',
70+
'3k': 'Extra Large 3072',
71+
'4k': 'Extra Large 4096',
72+
'f': 'VR 4K',
73+
'5k': 'Extra Large 5120',
74+
'6k': 'Extra Large 6144',
6875
'o': 'Original'
6976
};
70-
let returnValue = {};
77+
const returnValue = {};
78+
returnValue.sizeList = [];
7179
if (flickrJson && flickrJson.sizes.size) {
80+
// this code assumes that the sizes provided by flickr API are in ascending order
7281
for (let i = 0; i < flickrJson.sizes.size.length; i++) {
73-
returnValue = flickrJson.sizes.size[i];
82+
returnValue.sizeList.push(flickrJson.sizes.size[i]);
83+
returnValue.selectedSize = flickrJson.sizes.size[i];
7484
if (flickrJson.sizes.size[i].label === sizeTable[photo_size]) {
7585
break;
7686
}
7787
}
7888
}
89+
7990
return returnValue;
91+
},
92+
toBase58: function(num) {
93+
if (typeof num !== 'number') num = parseInt(num, 10);
94+
let enc = '';
95+
const alpha = '123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ';
96+
let div = num;
97+
let mod;
98+
while (num >= 58) {
99+
div = num / 58;
100+
mod = num - (58 * Math.floor(div));
101+
enc = '' + alpha.substr(mod, 1) + enc;
102+
num = Math.floor(div);
103+
}
104+
return div ? '' + alpha.substr(div, 1) + enc : enc;
80105
}
81106
};
82107

index.js

+37-13
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
/* eslint-disable linebreak-style */
21
/* global hexo */
32
/* eslint prefer-promise-reject-errors: 0*/
43
'use strict';
@@ -10,19 +9,27 @@ const tagUtil = require('./flickrTagUtil');
109

1110
const APIKey = hexo.config.flickr.api_key || false;
1211
const DefaultSize = hexo.config.flickr.default_size || '-'; // default size is medium
12+
const LinkToSource = hexo.config.flickr.linkto_source || true;
13+
14+
// Enable srcset
15+
const UseSrcset = hexo.config.flickr.use_srcset || true;
16+
1317
// use hexo-fs
1418
const fs = require('hexo-fs');
1519

1620
let cacheJson = [];
1721

1822
// option
1923
const cacheFilePath = hexo.config.flickr.cache_file_path || false;
20-
let cachePeriod = hexo.config.flickr.cache_expires || false;
21-
const enabledCache = !(!cacheFilePath && !cachePeriod);
22-
if (!cachePeriod) cachePeriod = Number(cachePeriod);
24+
25+
// default cache period is 24h, to comply with flickr TOS
26+
let cachePeriod = hexo.config.flickr.cache_expires || '86400000';
27+
if (cachePeriod) cachePeriod = Number(cachePeriod);
28+
29+
const enabledCache = cacheFilePath && cachePeriod;
2330

2431
// load cache file
25-
if (enabledCache && fs.existsSync(cacheFilePath)) {
32+
if (cacheFilePath && fs.existsSync(cacheFilePath)) {
2633
cacheJson = fs.readFileSync(cacheFilePath);
2734
cacheJson = JSON.parse(cacheJson);
2835
}
@@ -32,9 +39,9 @@ function getFlickrCacheJson(photoId) {
3239
if (!enabledCache) return null;
3340
const d = new Date();
3441
for (let i = 0; i < cacheJson.length; i++) {
35-
if (cacheJson[i].fl.id === photoId) {
42+
if (cacheJson[i].fl2.id === photoId) {
3643
if (cacheJson[i].expires > d.getTime()) {
37-
return cacheJson[i].fl;
44+
return cacheJson[i].fl2;
3845
}
3946
break;
4047
}
@@ -50,13 +57,13 @@ function pushImageSizeAndExpress_flickrJson(image, photo_id) {
5057
let isMatch = false;
5158

5259
for (let i = 0; i < cacheJson.length; i++) {
53-
if (cacheJson[i].fl.id === photo_id) {
54-
cacheJson[i].fl.img = image;
60+
if (cacheJson[i].fl2.id === photo_id) {
61+
cacheJson[i].fl2.img = image;
5562
cacheJson[i].expires = expiresTime;
5663
isMatch = true;
5764
}
5865
}
59-
if (!isMatch)cacheJson.push({'fl': {'id': photo_id, 'img': image}, 'expires': expiresTime });
66+
if (!isMatch)cacheJson.push({'fl2': {'id': photo_id, 'img': image}, 'expires': expiresTime });
6067
}
6168

6269
/**
@@ -69,7 +76,7 @@ const promiseRequest = function(tagArgs) {
6976
throw new Error('flickr.api_key configuration is required');
7077
}
7178

72-
const tag = tagUtil.convertAttr(tagArgs, DefaultSize);
79+
const tag = tagUtil.convertAttr(tagArgs, DefaultSize, UseSrcset);
7380

7481
return new Promise((resolve, reject) => {
7582

@@ -114,7 +121,6 @@ const promiseRequest = function(tagArgs) {
114121
});
115122
};
116123

117-
118124
/**
119125
* Flickr tag
120126
*
@@ -125,7 +131,13 @@ const promiseRequest = function(tagArgs) {
125131
*/
126132
hexo.extend.tag.register('flickr', (args, _) => {
127133
return promiseRequest(args).then(imgAttr_internal => {
128-
return hexoUtil.htmlTag('img', imgAttr_internal);
134+
const photoId = imgAttr_internal.photoId;
135+
delete imgAttr_internal.photoId;
136+
const img = hexoUtil.htmlTag('img', imgAttr_internal);
137+
if (LinkToSource) {
138+
return '<a href=\'https://flic.kr/p/' + tagUtil.toBase58(photoId) + '/sizes/l\' target=\'_blank\' rel=\'noopener noreferrer\'>' + img + '</a>';
139+
}
140+
return img;
129141
}, err => {
130142
hexo.log.error(err);
131143
});
@@ -138,6 +150,18 @@ hexo.extend.filter.register('after_generate', () => {
138150
}
139151
});
140152

153+
hexo.extend.filter.register('after_clean', () => {
154+
if (enabledCache) {
155+
return fs.exists(cacheFilePath).then(exist => {
156+
if (!exist) return;
157+
158+
return fs.unlink(cacheFilePath).then(() => {
159+
hexo.log.debug('Deleted flickr cache.');
160+
});
161+
});
162+
}
163+
});
164+
141165
/**
142166
* For gallery post
143167
*

package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "hexo-tag-flickr",
3-
"version": "0.4.0",
3+
"version": "0.5.0",
44
"description": "Embed flickr photo tag plugin for Hexo",
55
"main": "index",
66
"repository": {
@@ -27,7 +27,7 @@
2727
"mocha": "^8.1.3",
2828
"chai": "^4.2.0",
2929
"cheerio": "^1.0.0-rc.3",
30-
"eslint": "^7.10.0",
30+
"eslint": "^7.11.0",
3131
"eslint-config-hexo": "^4.1.0"
3232
},
3333
"bugs": {

test/index.js

+7-7
Original file line numberDiff line numberDiff line change
@@ -18,26 +18,26 @@ describe('Hexo Flickr Tag Plugin Util', () => {
1818
});
1919

2020
describe('tagUtil.imgFormat', () => {
21-
const jsonData = JSON.parse('{"photo":{"id": "9528576237", "secret": "b87fc8f98b", "server": "5445", "farm": 6, "dateuploaded": "1376748177", "isfavorite": 0, "license": 0, "safety_level": 0, "rotation": 0, "originalsecret": "2bf761518c", "originalformat": "jpg", "owner": { "nsid": "8891490@N04", "username": "visioncan", "realname": "", "location": "", "iconserver": "2891", "iconfarm": 3, "path_alias": "visioncan" }, "title": { "_content": "九份-阿妹茶樓" }}}');
21+
const jsonData = JSON.parse('{"selectedSize":{"label":"Square","width":75,"height":75,"source":"https://live.staticflickr.com/65535/50435880733_3b6d5f6a4b_s.jpg","url":"https://www.flickr.com/photos/tomapp/50435880733/sizes/sq/","media":"photo"}}');
2222

2323
it('should return image attr object', () => {
24-
const tag = tagUtil.convertAttr('class1 class2 9528576237 m'.split(' '));
24+
const tag = tagUtil.convertAttr('class1 class2 50435880733 m'.split(' '), 's');
2525
tagUtil.imgFormat(tag, jsonData).should.be.an('object').have.property('src');
2626
tagUtil.imgFormat(tag, jsonData).should.be.an('object').have.property('class');
2727
tagUtil.imgFormat(tag, jsonData).should.be.an('object').have.property('width');
2828
});
2929

3030
it('return correct image size', () => {
31-
const tag = tagUtil.convertAttr('class1 class2 9528576237 m'.split(' '));
32-
tagUtil.imgFormat(tag, jsonData).should.be.an('object').have.property('src').equal('https://farm6.staticflickr.com/5445/9528576237_b87fc8f98b_m.jpg');
31+
const tag = tagUtil.convertAttr('class1 class2 50435880733 m'.split(' '), 's');
32+
tagUtil.imgFormat(tag, jsonData).should.be.an('object').have.property('src').equal('https://live.staticflickr.com/65535/50435880733_3b6d5f6a4b_s.jpg');
3333
tagUtil.imgFormat(tag, jsonData).should.be.an('object').have.property('class').equal('class1 class2');
34-
tagUtil.imgFormat(tag, jsonData).should.be.an('object').have.property('width').equal(240);
34+
tagUtil.imgFormat(tag, jsonData).should.be.an('object').have.property('width').equal(75);
3535
});
3636

3737
it('return original image with html tag', () => {
38-
const tag = tagUtil.convertAttr('9528576237 o'.split(' '));
38+
const tag = tagUtil.convertAttr('9528576237 s'.split(' '));
3939
const $ = cheerio.load(hexoUtil.htmlTag('img', tagUtil.imgFormat(tag, jsonData)));
40-
$('img').attr('src').should.eql('https://farm6.staticflickr.com/5445/9528576237_2bf761518c_o.jpg');
40+
$('img').attr('src').should.eql('https://live.staticflickr.com/65535/50435880733_3b6d5f6a4b_s.jpg');
4141
});
4242
});
4343
});

0 commit comments

Comments
 (0)