Skip to content
This repository was archived by the owner on Jul 24, 2023. It is now read-only.

Commit 4262f4c

Browse files
committed
fix: update custom plugins
and put them in local plugins directory, instead of separate repos
1 parent fa9ce72 commit 4262f4c

File tree

10 files changed

+572
-0
lines changed

10 files changed

+572
-0
lines changed
Lines changed: 293 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,293 @@
1+
const select = require(`unist-util-select`)
2+
const path = require(`path`)
3+
const isRelativeUrl = require(`is-relative-url`)
4+
const _ = require(`lodash`)
5+
const { sizes } = require(`gatsby-plugin-sharp`)
6+
const Promise = require(`bluebird`)
7+
const cheerio = require(`cheerio`)
8+
const slash = require(`slash`)
9+
10+
// If the image is relative (not hosted elsewhere)
11+
// 1. Find the image file
12+
// 2. Find the image's size
13+
// 3. Filter out any responsive image sizes that are greater than the image's width
14+
// 4. Create the responsive images.
15+
// 5. Set the html w/ aspect ratio helper.
16+
module.exports = (
17+
{ files, markdownNode, markdownAST, pathPrefix, getNode, reporter },
18+
pluginOptions
19+
) => {
20+
const defaults = {
21+
maxWidth: 650,
22+
wrapperStyle: ``,
23+
backgroundColor: `white`,
24+
linkImagesToOriginal: true,
25+
showCaptions: false,
26+
addAspectRatio: false,
27+
pathPrefix,
28+
}
29+
30+
const options = _.defaults(pluginOptions, defaults)
31+
32+
// markdownAST = map(markdownAST, node => {
33+
// if (
34+
// node.type === `link` &&
35+
// node.children &&
36+
// node.children.length === 1 &&
37+
// node.children[0].type === `image`
38+
// ) {
39+
// const { url, title } = node
40+
// const image = node.children[0]
41+
// return {
42+
// type: image.type,
43+
// title: image.title,
44+
// url: image.url,
45+
// alt: image.alt,
46+
// position: image.position,
47+
// href: url,
48+
// hrefTitle: title,
49+
// }
50+
// }
51+
// return node
52+
// })
53+
54+
// // markdownAST.children = markdownAST.children.map()
55+
56+
// console.log(`\n\nTHE_AST\n`)
57+
// console.log(JSON.stringify(markdownAST, null, 2))
58+
59+
// This will only work for markdown syntax image tags
60+
const markdownImageNodes = select(markdownAST, `image`)
61+
// console.log(`\nMARKDOWNIMAGENODES`)
62+
// console.log(markdownImageNodes)
63+
// This will also allow the use of html image tags
64+
const rawHtmlNodes = select(markdownAST, `html`)
65+
66+
// Takes a node and generates the needed images and then returns
67+
// the needed HTML replacement for the image
68+
const generateImagesAndUpdateNode = async function(node, resolve) {
69+
// Check if this markdownNode has a File parent. This plugin
70+
// won't work if the image isn't hosted locally.
71+
const parentNode = getNode(markdownNode.parent)
72+
let imagePath
73+
if (parentNode && parentNode.dir) {
74+
imagePath = slash(path.join(parentNode.dir, node.url))
75+
} else {
76+
return null
77+
}
78+
79+
const imageNode = _.find(files, file => {
80+
if (file && file.absolutePath) {
81+
return file.absolutePath === imagePath
82+
}
83+
return null
84+
})
85+
86+
if (!imageNode || !imageNode.absolutePath) {
87+
return resolve()
88+
}
89+
90+
let responsiveSizesResult = await sizes({
91+
file: imageNode,
92+
args: options,
93+
reporter,
94+
})
95+
96+
if (!responsiveSizesResult) {
97+
return resolve()
98+
}
99+
100+
// Calculate the paddingBottom %
101+
const ratio = `${(1 / responsiveSizesResult.aspectRatio) * 100}%`
102+
103+
const originalImg = responsiveSizesResult.originalImg
104+
const fallbackSrc = responsiveSizesResult.src
105+
const srcSet = responsiveSizesResult.srcSet
106+
const presentationWidth = responsiveSizesResult.presentationWidth
107+
108+
// Generate default alt tag
109+
const srcSplit = node.url.split(`/`)
110+
const fileName = srcSplit[srcSplit.length - 1]
111+
const fileNameNoExt = fileName.replace(/\.[^/.]+$/, ``)
112+
const defaultAlt = fileNameNoExt.replace(/[^A-Z0-9]/gi, ` `)
113+
114+
// TODO
115+
// Fade in images on load.
116+
// https://www.perpetual-beta.org/weblog/silky-smooth-image-loading.html
117+
118+
// Construct new image node w/ aspect ratio placeholder
119+
let rawHTML = `
120+
<span
121+
class="gatsby-resp-image-wrapper"
122+
style="position: relative; display: block; ${
123+
options.wrapperStyle
124+
}; max-width: ${presentationWidth}px; margin-left: auto; margin-right: auto;"
125+
>
126+
<span
127+
class="gatsby-resp-image-background-image"
128+
style="padding-bottom: ${ratio}; position: relative; bottom: 0; left: 0; background-image: url('${
129+
responsiveSizesResult.base64
130+
}'); background-size: cover; display: block;"
131+
>
132+
<img
133+
class="gatsby-resp-image-image"
134+
style="width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px ${
135+
options.backgroundColor
136+
};"
137+
alt="${node.alt ? node.alt : defaultAlt}"
138+
title="${node.title ? node.title : ``}"
139+
src="${fallbackSrc}"
140+
srcset="${srcSet}"
141+
sizes="${responsiveSizesResult.sizes}"
142+
/>
143+
</span>
144+
</span>
145+
`
146+
147+
// Make linking to original image optional.
148+
if (node.href || options.linkImagesToOriginal) {
149+
rawHTML = `
150+
<a
151+
class="gatsby-resp-image-link"
152+
href="${node.href || originalImg}"
153+
style="display: block"
154+
target="_blank"
155+
rel="noopener"
156+
title="${node.hrefTitle ? node.hrefTitle : ``}"
157+
>
158+
${rawHTML}
159+
</a>
160+
`
161+
}
162+
163+
// Wrap in figure and use title as caption
164+
165+
if (options.showCaptions) {
166+
rawHTML = `
167+
<figure
168+
class="gatsby-resp-image-figure"
169+
${
170+
options.addAspectRatio
171+
? `data-ratio="${_.round(responsiveSizesResult.aspectRatio, 2)}"`
172+
: ``
173+
}
174+
>
175+
${rawHTML}
176+
${
177+
node.title
178+
? `<figcaption class="gatsby-resp-image-figcaption">${
179+
node.title
180+
}</figcaption>`
181+
: ``
182+
}
183+
</figure>
184+
`
185+
}
186+
187+
return rawHTML
188+
}
189+
190+
return Promise.all(
191+
// Simple because there is no nesting in markdown
192+
markdownImageNodes.map(
193+
node =>
194+
new Promise(async (resolve, reject) => {
195+
const fileType = node.url.slice(-3)
196+
197+
// Ignore gifs as we can't process them,
198+
// svgs as they are already responsive by definition
199+
if (
200+
isRelativeUrl(node.url) &&
201+
fileType !== `gif` &&
202+
fileType !== `svg`
203+
) {
204+
const rawHTML = await generateImagesAndUpdateNode(node, resolve)
205+
206+
if (rawHTML) {
207+
// Replace the image node with an inline HTML node.
208+
node.type = `html`
209+
node.value = rawHTML
210+
}
211+
return resolve(node)
212+
} else {
213+
// Image isn't relative so there's nothing for us to do.
214+
return resolve()
215+
}
216+
})
217+
)
218+
).then(markdownImageNodes =>
219+
// HTML image node stuff
220+
Promise.all(
221+
// Complex because HTML nodes can contain multiple images
222+
rawHtmlNodes.map(
223+
node =>
224+
new Promise(async (resolve, reject) => {
225+
if (!node.value) {
226+
return resolve()
227+
}
228+
229+
const $ = cheerio.load(node.value)
230+
if ($(`img`).length === 0) {
231+
// No img tags
232+
return resolve()
233+
}
234+
235+
let imageRefs = []
236+
$(`img`).each(function() {
237+
imageRefs.push($(this))
238+
})
239+
240+
for (let thisImg of imageRefs) {
241+
// Get the details we need.
242+
let formattedImgTag = {}
243+
formattedImgTag.url = thisImg.attr(`src`)
244+
formattedImgTag.title = thisImg.attr(`title`)
245+
formattedImgTag.alt = thisImg.attr(`alt`)
246+
247+
if (!formattedImgTag.url) {
248+
return resolve()
249+
}
250+
251+
const fileType = formattedImgTag.url.slice(-3)
252+
253+
// Ignore gifs as we can't process them,
254+
// svgs as they are already responsive by definition
255+
if (
256+
isRelativeUrl(formattedImgTag.url) &&
257+
fileType !== `gif` &&
258+
fileType !== `svg`
259+
) {
260+
const rawHTML = await generateImagesAndUpdateNode(
261+
formattedImgTag,
262+
resolve
263+
)
264+
265+
if (rawHTML) {
266+
// Replace the image string
267+
thisImg.replaceWith(rawHTML)
268+
} else {
269+
return resolve()
270+
}
271+
}
272+
}
273+
274+
// Replace the image node with an inline HTML node.
275+
node.type = `html`
276+
node.value = $(`body`).html() // fix for cheerio v1
277+
278+
return resolve(node)
279+
})
280+
)
281+
)
282+
.then(htmlImageNodes =>
283+
markdownImageNodes.concat(htmlImageNodes).filter(node => !!node)
284+
)
285+
.catch(error => {
286+
console.error(`\n`)
287+
console.error(`gatsby-remark-images-with-ratio`)
288+
console.error(error)
289+
console.error(`gatsby-remark-images-with-ratio`)
290+
console.error(`\n`)
291+
})
292+
)
293+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"name": "gatsby-remark-images-with-ratio",
3+
"version": ""
4+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
const cheerio = require(`cheerio`)
2+
const modifyChildren = require(`unist-util-modify-children`)
3+
const fs = require(`fs`)
4+
5+
module.exports = ({ markdownAST }, pluginOptions) => {
6+
markdownAST.children
7+
.filter(x => x && x.children && x.children.length)
8+
.map(modifyChildren(modifier))
9+
10+
return markdownAST
11+
}
12+
13+
function modifier(node, index, parent) {
14+
if (parent.type !== `paragraph`) return false
15+
16+
const whitespaceStripped = parent.children.filter(
17+
x => !/^(\\n)*\s+$/.test(x.value)
18+
)
19+
20+
const onlyContainsImages = whitespaceStripped.every(
21+
x => x.type === `html` && x.value.includes(`gatsby-resp-image-figure`)
22+
)
23+
24+
if (onlyContainsImages) {
25+
parent.type = `div`
26+
parent.data = {
27+
hProperties: {
28+
class: `inline-gallery`,
29+
},
30+
}
31+
parent.children.map(x => {
32+
const $ = cheerio.load(x.value)
33+
const imageWithRatio = $(`[data-ratio]`)
34+
if (imageWithRatio) {
35+
if (parent.children.length > 1) {
36+
imageWithRatio.css(`flex`, imageWithRatio.attr(`data-ratio`))
37+
}
38+
imageWithRatio.attr(`data-ratio`, null)
39+
x.value = $(`body`).html()
40+
}
41+
})
42+
parent.children = whitespaceStripped
43+
}
44+
45+
return index + 1
46+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"name": "gatsby-remark-wrap-images",
3+
"version": ""
4+
}

0 commit comments

Comments
 (0)