-
-
Notifications
You must be signed in to change notification settings - Fork 10k
/
img_url.js
126 lines (98 loc) · 4.19 KB
/
img_url.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
// Usage:
// `{{img_url feature_image}}`
// `{{img_url profile_image absolute="true"}}`
// Note:
// `{{img_url}}` - does not work, argument is required
//
// Returns the URL for the current object scope i.e. If inside a post scope will return image permalink
// `absolute` flag outputs absolute URL, else URL is relative.
const url = require('url');
const _ = require('lodash');
const proxy = require('./proxy');
const urlUtils = proxy.urlUtils;
const STATIC_IMAGE_URL_PREFIX = `${urlUtils.STATIC_IMAGE_URL_PREFIX}`;
module.exports = function imgUrl(requestedImageUrl, options) {
// CASE: if no url is passed, e.g. `{{img_url}}` we show a warning
if (arguments.length < 2) {
proxy.logging.warn(proxy.i18n.t('warnings.helpers.img_url.attrIsRequired'));
return;
}
// CASE: if url is passed, but it is undefined, then the attribute was
// an unknown value, e.g. {{img_url feature_img}} and we also show a warning
if (requestedImageUrl === undefined) {
proxy.logging.warn(proxy.i18n.t('warnings.helpers.img_url.attrIsRequired'));
return;
}
// CASE: if you pass e.g. cover_image, but it is not set, then requestedImageUrl is null!
// in this case we don't show a warning
if (requestedImageUrl === null) {
return;
}
// CASE: if you pass an external image, there is nothing we want to do to it!
const isInternalImage = detectInternalImage(requestedImageUrl);
if (!isInternalImage) {
return requestedImageUrl;
}
const {requestedSize, imageSizes} = getImageSizeOptions(options);
const absoluteUrlRequested = getAbsoluteOption(options);
function applyImageSizes(image) {
return getImageWithSize(image, requestedSize, imageSizes);
}
function getImageUrl(image) {
return urlUtils.urlFor('image', {image}, absoluteUrlRequested);
}
function ensureRelativePath(image) {
return urlUtils.absoluteToRelative(image);
}
// CASE: only make paths relative if we didn't get a request for an absolute url
const maybeEnsureRelativePath = !absoluteUrlRequested ? ensureRelativePath : _.identity;
return maybeEnsureRelativePath(
getImageUrl(
applyImageSizes(requestedImageUrl)
)
);
};
function getAbsoluteOption(options) {
const absoluteOption = options && options.hash && options.hash.absolute;
return absoluteOption ? !!absoluteOption && absoluteOption !== 'false' : false;
}
function getImageSizeOptions(options) {
const requestedSize = options && options.hash && options.hash.size;
const imageSizes = options && options.data && options.data.config && options.data.config.image_sizes;
return {
requestedSize,
imageSizes
};
}
function detectInternalImage(requestedImageUrl) {
const siteUrl = urlUtils.getBlogUrl();
const isAbsoluteImage = /https?:\/\//.test(requestedImageUrl);
const isAbsoluteInternalImage = isAbsoluteImage && requestedImageUrl.startsWith(siteUrl);
// CASE: imagePath is a "protocol relative" url e.g. "//www.gravatar.com/ava..."
// by resolving the the imagePath relative to the blog url, we can then
// detect if the imagePath is external, or internal.
const isRelativeInternalImage = !isAbsoluteImage && url.resolve(siteUrl, requestedImageUrl).startsWith(siteUrl);
return isAbsoluteInternalImage || isRelativeInternalImage;
}
function getImageWithSize(imagePath, requestedSize, imageSizes) {
const hasLeadingSlash = imagePath[0] === '/';
if (hasLeadingSlash) {
return '/' + getImageWithSize(imagePath.slice(1), requestedSize, imageSizes);
}
if (!requestedSize) {
return imagePath;
}
if (!imageSizes || !imageSizes[requestedSize]) {
return imagePath;
}
const {width, height} = imageSizes[requestedSize];
if (!width && !height) {
return imagePath;
}
const [imgBlogUrl, imageName] = imagePath.split(STATIC_IMAGE_URL_PREFIX);
const sizeDirectoryName = prefixIfPresent('w', width) + prefixIfPresent('h', height);
return [imgBlogUrl, STATIC_IMAGE_URL_PREFIX, `/size/${sizeDirectoryName}`, imageName].join('');
}
function prefixIfPresent(prefix, string) {
return string ? prefix + string : '';
}