From 65a0554d52208839ffc17fd5eda2c475437ac63a Mon Sep 17 00:00:00 2001 From: LB Date: Fri, 21 Jun 2019 12:03:32 -0400 Subject: [PATCH 01/11] Create gatsby-image-tutorial --- docs/tutorial/gatsby-image-tutorial | 275 ++++++++++++++++++++++++++++ 1 file changed, 275 insertions(+) create mode 100644 docs/tutorial/gatsby-image-tutorial diff --git a/docs/tutorial/gatsby-image-tutorial b/docs/tutorial/gatsby-image-tutorial new file mode 100644 index 0000000000000..e876087e9ebe0 --- /dev/null +++ b/docs/tutorial/gatsby-image-tutorial @@ -0,0 +1,275 @@ +--- +title: "Using Gatsby-Image With Your Site Tutorial" +--- + +### Setting Expectations + +This tutorial assumes you already have a gatsby project up and running as well as images you'd like to render on your page. + +In this tutorial we'll review how to set up `gatsby-image`, a number of ways to use the plugin and some gotchas. Note that this tutorial is using examples of static content stored in yaml files, but similar methods can be used for markdown files. + +### Getting started + +Image optimization in Gatsby is provided by a plugin called `gatsby-image` which is incredibly performant. In order to make use of it you'll start by using npm to install that plugin and its associated dependencies. + +``` +npm install gatsby-image gatsby-transformer-sharp gatsby-plugin-sharp +``` + +Once that's done, you want to add the newly installed plugins to you `gatsby-config.js` file. The config file ends up looking like this (other plugins already in use have been removed from this snippet for simplicity). Note that once `gatsby-image` has been installed it does not need to be included in the gatsby-config.js file. + +```jsx +plugins: [`gatsby-transformer-sharp`, `gatsby-plugin-sharp`] +``` + +### Gatsby-image Configuration + +Now you're set up to use `gatsby-image`. The first thing to do determine where your image files are located. In this example they're in `src/data`. + +If you haven't already, make sure that your project is set up to see content inside that directory. That means doing two things. If you created your project using `gatsby new ` then the first step is already done for you. + +``` +npm install gatsby-source-filesystem +``` + +The second step is to make sure your `gatsby-config.js` file specifies the correct folder. In this example it would look like this. + +```jsx +{ resolve: `gatsby-source-filesystem`, + options: { path: `./src/data/` } +} +``` + +Now you're ready to go. + +### Single Image Query + +Your first option is to use `graphql` to query an image file directly. You can include the relative path to the image file and determine how you want `gatsby-image` to process the file. + +```jsx +export const query = graphql` + query { + file(relativePath: { eq: "headers/headshot.jpg" }) { + childImageSharp { + fixed(width: 125, height: 125) { + ...GatsbyImageSharpFixed + } + } + } + } +` +``` + +There are a couple of things to note here. You might expect the relative path to be relative to the file the code sits in, in this case that's index.js. However, that doesn't work. The relative path is actually based on the line of code you put in the `gatsby-source-filesystem` config, which points to `src/data`. + +Another thing to note is that this query is using `GatsbyImageSharpFixed`. Another option is `GatsbyImageSharpFluid` which will not take specific dimension specifications. In `gatsby-image`, fluid images are meant for images that don’t have a finite size depending on the screen, where as other images are fixed. + +The query will return a processed image at the highest depth. The result will be automatically passed into the component and attached to `data`. Using JSX you can display the image. + +Start by importing the image tag provided by `gatsby-image`. + +```jsx +import Img from "gatsby-image" +``` + +Now you can use it. Note that the key for pointing to the image corresponds to the way in which the image was processed. In this example that is `fixed`. + +```jsx +headshot +``` + +### Querying Yaml + +Another way to access images is through yaml (or markdown). This example uses the `gatsby-transformer-yaml` plugin to query the yaml files. More information about that plugin can be found [here](https://www.gatsbyjs.org/packages/gatsby-transformer-yaml/?=gatsby-transformer-yaml). + +A brief example of a yaml query is this. + +```jsx +{ + allSpeakingYaml { + edges { + node { + conference + year + } + } + } +} +``` + +In this case the query starts with `allSpeakingYaml` to direct `graphql` to look for this data in the speaking.yaml file. If you want to query a file named blog.yaml, for example, you'd start the query with allBlogYaml. + +A common error with this is `Unknown field allSpeakingYaml on type Query`. What the error boils down to is that `graphql` is unable to find a matching result. This can mean it couldn't find a file that matched the first line, meaning that no `speaking.yaml` file exists. It can also be triggered by finding the file but not the associated content structure the query asks for. Yet another way to find this error is by leaving out the system-file plugin; without it, the folder that holds the data is not visible to `graphql` and it will throw the same error. + +### Yaml and Images + +In order to reference your images in yaml make sure that the relative path is accurate. The path to the image should be relative to the location of the `.yaml` file pointing to it. And all of these files need to be in a directory visible to the `gatsby-source-filesystem` plugin. + +The inside of the yaml file would look something like this. + +``` +- image: speaking/kcdc.jpg +``` + +Now, you can create the query. Similar to the single use example above, you can use `gatsby-image` features inside the query. When the query runs, the relative path will point to the location of the image file and the resulting query processes the file as an image for display. + +```jsx +{ + allSpeakingYaml { + edges { + node { + image { + childImageSharp { + fluid { + ...GatsbyImageSharpFluid + } + } + } + } + } + } +} +``` + +Since the images are stored as part of an array, they can be accessed using the map function in JSX. As with the single image example, the actual processed image is at the `...GatsbyImageSharpFluid` level. + +```jsx +{node.conference} +``` + +### Static Query + +If your query is part of a reusable component you may want to use a Static Query hook. The code necessary to do this is almost the same as the single image use case above. + +```jsx +export default () => { + const data = useStaticQuery(graphql` + query { + file(relativePath: { eq: "headers/default.jpg" }) { + childImageSharp { + fixed(width: 125, height: 125) { + ...GatsbyImageSharpFixed + } + } + } + } + `) + + return +} +``` + +Instead of a query constant and data that references the result, you can use a static query hook directly in the JXS code and then reference it. Note that the query language didn’t change and neither did the `Img` tag syntax, the only change was the location of the query and the usage of the `useStaticQuery` function to wrap it. + +### Multiple Queries and Aliasing + +The last use case you may come across is how to handle a situation where you have multiple queries in the same file/page. + +This example is attempting to query for all the data in `speaking.yaml` and the direct file query in our first example. In order to do this you want to use aliasing. + +The first thing to know is that an alias is assigning a name to a query. Below is a simple example. + +```jsx +talks: allSpeakingYaml { + edges { + node { + image { + childImageSharp { + fluid { + ...GatsbyImageSharpFluid + } + } + } + } + } + } +} +``` + +When you do that, you’ve changed the reference to that object in your JSX. While it was previously referenced as + +```jsx +{data.allSpeakingYaml.edges.map(({ node }) => ()) +``` + +giving it an alias does not add a level of complexity to the response object, it just replaces it. So you end up with the same structure referenced as + +```jsx +{data.talks.edges.map(({ node }) => ()) +``` + +The top-level object name of data is implicit. This is important because when you conduct multiple queries as part of a single component `Gatsby` still passes the entire result to the component. + +```jsx +const SpeakingPage = ({ data}) => {}) +``` + +everything else gets referenced from that top-level return +name. + +With that understanding, you can combine two queries and use aliasing to distinguish between them. + +```jsx +{ + allSpeakingYaml { + edges { + node { + image { + childImageSharp { + fluid { + ...GatsbyImageSharpFluid + } + } + } + } + } + } + banner: file(relativePath: { eq: "headers/default.jpg" }) { + childImageSharp { + fluid { + ...GatsbyImageSharpFluid + } + } + } +} +``` + +Notice that this example uses aliasing for one query and not the other. This is allowed; there is no requirement that all your queries use aliasing. In this case, the JSX would look like this to access the `speaking.yaml` content. + +```jsx +{data.allSpeakingYaml.edges.map(({ node }) => ()) +``` + +And then like this to access the image using the alias name `banner`. + +```jsx + +``` + +### Aspect Ratio + +These examples should handle a fair number of your use cases. A couple bonus things. First, `gatsby-image` has a nice feature that gives you the ability to set an aspect ratio. This can be used for fixed or fluid processed images, it doesn't matter. + +```jsx + +``` + +### Bonus Error + +Now for errors to watch out for. If you change your image processing from `fixed` to `fluid` you may see this error. + +![In image cache error message.](https://tenmilesquare.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-18-at-11.46.03-AM-1024x212.png) + +Despite its appearance, solving this doesn't actually require flushing any kind of cache. In reality, it has to do with incompatible references. You likely triggered it because you changed the query to process the image as `fluid` but the JSX key was still set to `fixed`, or visa versa. + +### The End + +So that's it. This post included a number of different possible use cases, so don't feel as if you need to explore them all. Pick the examples and tips that apply to your implementation. From 09d30cec42330078ffadeca10c10bdd3293da25f Mon Sep 17 00:00:00 2001 From: laurie Date: Mon, 1 Jul 2019 11:13:44 -0400 Subject: [PATCH 02/11] gatsby-image rework --- docs/tutorial/gatsby-image-tutorial | 275 ------------- .../gatsby-image-tutorial/ErrorMessage.png | Bin 0 -> 19391 bytes .../gatsby-image-tutorial.md | 361 ++++++++++++++++++ 3 files changed, 361 insertions(+), 275 deletions(-) delete mode 100644 docs/tutorial/gatsby-image-tutorial create mode 100644 docs/tutorial/gatsby-image-tutorial/ErrorMessage.png create mode 100644 docs/tutorial/gatsby-image-tutorial/gatsby-image-tutorial.md diff --git a/docs/tutorial/gatsby-image-tutorial b/docs/tutorial/gatsby-image-tutorial deleted file mode 100644 index e876087e9ebe0..0000000000000 --- a/docs/tutorial/gatsby-image-tutorial +++ /dev/null @@ -1,275 +0,0 @@ ---- -title: "Using Gatsby-Image With Your Site Tutorial" ---- - -### Setting Expectations - -This tutorial assumes you already have a gatsby project up and running as well as images you'd like to render on your page. - -In this tutorial we'll review how to set up `gatsby-image`, a number of ways to use the plugin and some gotchas. Note that this tutorial is using examples of static content stored in yaml files, but similar methods can be used for markdown files. - -### Getting started - -Image optimization in Gatsby is provided by a plugin called `gatsby-image` which is incredibly performant. In order to make use of it you'll start by using npm to install that plugin and its associated dependencies. - -``` -npm install gatsby-image gatsby-transformer-sharp gatsby-plugin-sharp -``` - -Once that's done, you want to add the newly installed plugins to you `gatsby-config.js` file. The config file ends up looking like this (other plugins already in use have been removed from this snippet for simplicity). Note that once `gatsby-image` has been installed it does not need to be included in the gatsby-config.js file. - -```jsx -plugins: [`gatsby-transformer-sharp`, `gatsby-plugin-sharp`] -``` - -### Gatsby-image Configuration - -Now you're set up to use `gatsby-image`. The first thing to do determine where your image files are located. In this example they're in `src/data`. - -If you haven't already, make sure that your project is set up to see content inside that directory. That means doing two things. If you created your project using `gatsby new ` then the first step is already done for you. - -``` -npm install gatsby-source-filesystem -``` - -The second step is to make sure your `gatsby-config.js` file specifies the correct folder. In this example it would look like this. - -```jsx -{ resolve: `gatsby-source-filesystem`, - options: { path: `./src/data/` } -} -``` - -Now you're ready to go. - -### Single Image Query - -Your first option is to use `graphql` to query an image file directly. You can include the relative path to the image file and determine how you want `gatsby-image` to process the file. - -```jsx -export const query = graphql` - query { - file(relativePath: { eq: "headers/headshot.jpg" }) { - childImageSharp { - fixed(width: 125, height: 125) { - ...GatsbyImageSharpFixed - } - } - } - } -` -``` - -There are a couple of things to note here. You might expect the relative path to be relative to the file the code sits in, in this case that's index.js. However, that doesn't work. The relative path is actually based on the line of code you put in the `gatsby-source-filesystem` config, which points to `src/data`. - -Another thing to note is that this query is using `GatsbyImageSharpFixed`. Another option is `GatsbyImageSharpFluid` which will not take specific dimension specifications. In `gatsby-image`, fluid images are meant for images that don’t have a finite size depending on the screen, where as other images are fixed. - -The query will return a processed image at the highest depth. The result will be automatically passed into the component and attached to `data`. Using JSX you can display the image. - -Start by importing the image tag provided by `gatsby-image`. - -```jsx -import Img from "gatsby-image" -``` - -Now you can use it. Note that the key for pointing to the image corresponds to the way in which the image was processed. In this example that is `fixed`. - -```jsx -headshot -``` - -### Querying Yaml - -Another way to access images is through yaml (or markdown). This example uses the `gatsby-transformer-yaml` plugin to query the yaml files. More information about that plugin can be found [here](https://www.gatsbyjs.org/packages/gatsby-transformer-yaml/?=gatsby-transformer-yaml). - -A brief example of a yaml query is this. - -```jsx -{ - allSpeakingYaml { - edges { - node { - conference - year - } - } - } -} -``` - -In this case the query starts with `allSpeakingYaml` to direct `graphql` to look for this data in the speaking.yaml file. If you want to query a file named blog.yaml, for example, you'd start the query with allBlogYaml. - -A common error with this is `Unknown field allSpeakingYaml on type Query`. What the error boils down to is that `graphql` is unable to find a matching result. This can mean it couldn't find a file that matched the first line, meaning that no `speaking.yaml` file exists. It can also be triggered by finding the file but not the associated content structure the query asks for. Yet another way to find this error is by leaving out the system-file plugin; without it, the folder that holds the data is not visible to `graphql` and it will throw the same error. - -### Yaml and Images - -In order to reference your images in yaml make sure that the relative path is accurate. The path to the image should be relative to the location of the `.yaml` file pointing to it. And all of these files need to be in a directory visible to the `gatsby-source-filesystem` plugin. - -The inside of the yaml file would look something like this. - -``` -- image: speaking/kcdc.jpg -``` - -Now, you can create the query. Similar to the single use example above, you can use `gatsby-image` features inside the query. When the query runs, the relative path will point to the location of the image file and the resulting query processes the file as an image for display. - -```jsx -{ - allSpeakingYaml { - edges { - node { - image { - childImageSharp { - fluid { - ...GatsbyImageSharpFluid - } - } - } - } - } - } -} -``` - -Since the images are stored as part of an array, they can be accessed using the map function in JSX. As with the single image example, the actual processed image is at the `...GatsbyImageSharpFluid` level. - -```jsx -{node.conference} -``` - -### Static Query - -If your query is part of a reusable component you may want to use a Static Query hook. The code necessary to do this is almost the same as the single image use case above. - -```jsx -export default () => { - const data = useStaticQuery(graphql` - query { - file(relativePath: { eq: "headers/default.jpg" }) { - childImageSharp { - fixed(width: 125, height: 125) { - ...GatsbyImageSharpFixed - } - } - } - } - `) - - return -} -``` - -Instead of a query constant and data that references the result, you can use a static query hook directly in the JXS code and then reference it. Note that the query language didn’t change and neither did the `Img` tag syntax, the only change was the location of the query and the usage of the `useStaticQuery` function to wrap it. - -### Multiple Queries and Aliasing - -The last use case you may come across is how to handle a situation where you have multiple queries in the same file/page. - -This example is attempting to query for all the data in `speaking.yaml` and the direct file query in our first example. In order to do this you want to use aliasing. - -The first thing to know is that an alias is assigning a name to a query. Below is a simple example. - -```jsx -talks: allSpeakingYaml { - edges { - node { - image { - childImageSharp { - fluid { - ...GatsbyImageSharpFluid - } - } - } - } - } - } -} -``` - -When you do that, you’ve changed the reference to that object in your JSX. While it was previously referenced as - -```jsx -{data.allSpeakingYaml.edges.map(({ node }) => ()) -``` - -giving it an alias does not add a level of complexity to the response object, it just replaces it. So you end up with the same structure referenced as - -```jsx -{data.talks.edges.map(({ node }) => ()) -``` - -The top-level object name of data is implicit. This is important because when you conduct multiple queries as part of a single component `Gatsby` still passes the entire result to the component. - -```jsx -const SpeakingPage = ({ data}) => {}) -``` - -everything else gets referenced from that top-level return -name. - -With that understanding, you can combine two queries and use aliasing to distinguish between them. - -```jsx -{ - allSpeakingYaml { - edges { - node { - image { - childImageSharp { - fluid { - ...GatsbyImageSharpFluid - } - } - } - } - } - } - banner: file(relativePath: { eq: "headers/default.jpg" }) { - childImageSharp { - fluid { - ...GatsbyImageSharpFluid - } - } - } -} -``` - -Notice that this example uses aliasing for one query and not the other. This is allowed; there is no requirement that all your queries use aliasing. In this case, the JSX would look like this to access the `speaking.yaml` content. - -```jsx -{data.allSpeakingYaml.edges.map(({ node }) => ()) -``` - -And then like this to access the image using the alias name `banner`. - -```jsx - -``` - -### Aspect Ratio - -These examples should handle a fair number of your use cases. A couple bonus things. First, `gatsby-image` has a nice feature that gives you the ability to set an aspect ratio. This can be used for fixed or fluid processed images, it doesn't matter. - -```jsx - -``` - -### Bonus Error - -Now for errors to watch out for. If you change your image processing from `fixed` to `fluid` you may see this error. - -![In image cache error message.](https://tenmilesquare.com/wp-content/uploads/2019/02/Screen-Shot-2019-02-18-at-11.46.03-AM-1024x212.png) - -Despite its appearance, solving this doesn't actually require flushing any kind of cache. In reality, it has to do with incompatible references. You likely triggered it because you changed the query to process the image as `fluid` but the JSX key was still set to `fixed`, or visa versa. - -### The End - -So that's it. This post included a number of different possible use cases, so don't feel as if you need to explore them all. Pick the examples and tips that apply to your implementation. diff --git a/docs/tutorial/gatsby-image-tutorial/ErrorMessage.png b/docs/tutorial/gatsby-image-tutorial/ErrorMessage.png new file mode 100644 index 0000000000000000000000000000000000000000..8f6d1296c46f25ba7ac63d1f70d3ad0d5455bad2 GIT binary patch literal 19391 zcmW(+Wmud&vwjwLcX!uPT#LI~3&mZEQ=G-!rMMJ#DDI0Dio0uZFYfGlzw;-aYciQT zxh6A{D0NjibQBU4007Vx2cnEhWSqpqwi^LleTPR4cA)@5d5 z@jN;C_Vj#zdl3E85Tq!j*-=E3`N7Ie9vh&NsQd%vUd$UPt}+ zk1!si>84v;M%C9ZsR4fnql{y;0M(qwAp!X9|0=P)jDVwAQ9wVpVj!jEf5SEKWfg}LDjtjtfb@1YQrqfX=<3AE_{kMj7d?4!) z1YgdVZq8pxbr(Ei90tSHGONB_<3{|+Naah9I&hJ~AT~O^UHeTZ@xC~3gYOC`FH#f5 znbiW~B@&k6&jZgW8|j}&@xWqMzPL0UxvV2K8=eIlMPUdKS}PbIdgsIsvESgq=@Y*l zcYpAM<(Tg&+SA2_?O-i_H^QTUmO~5u_oxjoxV-%QE?X~Ey1qIIf9M?Dc!)C{dyg~n zUJ2{zlH<9s&sD}8Ke9<$^rC|~mfvE;xJ|cQ$&r@eEAN1>#9>jjTqKB3b5r%81yq`~ zbt{FEYFZfs3%+C&3Y}puME@A?cz0088iiC3G%gk%i-@o_-YC%CB7=#EY&xWxEzL>3 zijDKBAo+ha;b@uA5&)I0vo-j_!3XBuvpU?_m0Rj*mnjicBkE_Jiy+sTZHFmgm*x?T zVyCBmns0BzwK~t0bJ6^>de$A4!bU>RC{@02+>Tv~bEMx>ULZGd3$M?vz?oMxEZU*w zj1?U}OF>F*Fhi06`%cYy{=Jp*UUs-ZoOrGVut5S~#vjwp<+fpi?-jX;iZ|DRQUI2# z0i8>}k9tClDNq~kV+|_ooaJVCZmt#CJ-#$VUA#Z5F6d9Aa1+*H7VL(6-BjFH+!(@# zSUOrgkiO}HRu!Y_XcyCYyXxj}e_-(#}a+$&6EB znQ!OM&k9Vs%kpTRk(`Y$9y;n?YNWJpqu6#2F5@jlw7 zyaf2e&ZeB+%G9WEa&-4fJ%6`|?m0(D{93Sy(o*~s8TDzIit2k0tj(3r;?ay}TAWo} z>kw9XXPTX9A3W98Ef$cOzZWq}{2hjhexz}Lk~a=~5}Xtu#?VVtc+T`NO){y1T2s&U zlf(s9UiYQ+gD=*5LU)yht8Q4K(O6-T&Xx5R^mAPh(}LpXif=Ph%4IF`lEHgeFl#Cb z!nB{Uc5~Wvej9#=D|mE?Oe&;)t5!850ey5ZN?(pBK`S?01G|J1f=67c{;RYh1*@Okd z@Gr1~B+Q#>TeT&v)Gv_06XQl9>Fxxe`Ng9$ByeG*gvn;n*VTEtZzLd#T*Fx4WQa^+ zHwvJ`O{WDEd^w6X*;4A<`fm{7e)l^!Qrkd&@!jy#=uxjbsbZ&NwPZ*zAwX7mT7q?a z!?cy0GftxbFQVBdQ$NV~O2s7T$d1LI5cH2Ezm5l}_ZD7nSL7*0PQ?WrFu=9f!~hon zZpSPnDQ3WrI3xpm{Q(gv&v?=l(HJ!(ycJ|y-YHbyb7dfbFQ@z!%iYI+ay2<)n7Cq5 zTCimM4NJlm7=a{$a8rtybM1cZBT2-ge`F!oA{;!W638X~w04vch`y}xz3l^8b&wlZ z&iQkKU^Tsf<5@L^d@J zR_DNrn^CMd&(Z zB|L_J1UrjeF3&%fAvoadZG3$ZCar*zH}fAFP)wUaQ}2Hv3)}Kk3t3@^Y54NK*8fDqFef0cMNAi7^=>4H3e^FFL7GwbLU~t zLvcDUS|H%QL-xLo05_rFaY%g0OG<;a$xc{ zj|SjWk+*Io7NO0O-nrt`6O6Hxh0Lrn5U}R`veAa~x3ps53u`8#LuDOL)|To<2AtjQ zL=d^Sm}+1&#VR5@%?ZJ$ZjI>=u0LYdu_YKnd#K#)MO01cu63P(Kn|^4XVHN zvnD*_v5K*EiGyp{ZY-JwWj%4Hx&nlA811oc%Sx}%aiweX1NW${7BcI_Nf$xj@$e1y zoa?hlOn@oxUMv0B;nf@Y^ps+7pCR-ssRWs<&N7HGBeMP}d!cS*BC?>zxYV;}g}WFGwIwRCK@op_`+}_=YUI3M z(@2QD2awCVAu%;1Yee9cHD*{XTsT03(w<$mAbdFkv3CIR>_)o*8TI}S&JPxFws8{b z>L?7~*{3!0d3R$7y`uif9dsGX?SKF{-(FDgnM!>e8g|fMK==tmTU|v?_|YupFxuk- z_M%fdsL&jjVnj>|W4meYRHm0kn*CzW{frDELr9)c-|`L*5R%9J%uAR`uYBeQZNFk3 zpLARH@34D0t^C*Z)qN%(7Kn#4AMS_BH^XpjL-7L&4X_)_WqvQd4(4#`tS_ z#v05}lLeJfyI^$8W^>zB(d{Rm*E9=1HOp!%!-nPl_%*Ox*0+YkFKAVy(s+%n3}kkF zIFyN92$dS|xaMUDNEB#)`Urb95-R0M#lU=&xbGlR{z5v3^SH;(k7T_&rqPZ=30J}F zv7wwr5!=!%!CIpK)~`1Q?@v)2ntS?5%lbK{wiXrtW{^5FHCPvVbudz>q$AIuzKS3M zem0sP`TpB58G8_LZq8Oc+EV>5{#=8gB!{56-8>TuCXN&e(^(U4{))_D#Glx(HRTM+ zHia?n&*#!z+~tEMpjzHu0vgVPF_Z{`jJMFSlM4m+Tpa{B14naGeKqo9ei>x{XwSVn z{<4=h6Ap_YkNA`51?}b9^t^(OtU#%Od@Boz@oHnR(yOQQNvpR@6bT`^tLEYt85jmS}Wk1rh)Gc1J;%18yo-%44BlpN&tpwOpY4WJ8*A-J#c-mn??N&X=YPh zJBx9wss*wuH~WJEk3w8DG*!ntW%2-Vc$vDXSp^D-!DQb>bM&4!N#AZ`w zN;JVqpe_wa>d-LGtFZ5gdgzl-=g zF9p5aY*oQTusXq{V=_Onf^OA7lgQgeZ29!LsO!gQ^&XLx*T2%>-{MxbwmjfR?I&3I4p`YcTU9sO*6i8F5JLaf4*M&#}k;wr>GERH4Oy#1Y;?BTf=_Wf)b zx)QH<#s;c3xgUt?epM^jjnWSijiaHMLGg{-F%lz1yl6Kv8r^qc)=j&`EML!qlG#%eCGtr8{J~|N z#>xH0ux(@@^7L`4_bcXc30TKS5{5HY^$1fs%w6(FIX!oYy7o_XZXI~-pRUYNuF-Z7 z8@G%^iIULbp9LO2tq>CHvywV$)8Pv;k}uHb)3m2W%h`qSCy1?~`^p-BD)_K)lAe$i zmVdeW3~r(&W$*?hx6v zW9g&JwYHp4t7wju6n|kZVFdTzsf|hcg9>mIv`@^{fcd5c&9_v$hg?8fQxmHEIokP= z20Kmt2o+#yCLwrYAS4l#k8)5@G+>Fcqeq=j6(}2TYJ~$wtZi4g2d*vf1qip?EQFGF^U}7qqPgIaYh?4fuJrnpq$P%jFHnp4ws4wG4uxHnw&}3vth=Ef1 zYIc{NC5r9LYm(>zxMxfh?hK> z+;cu(g#wWakPFg-m|Y`Z{)-6uZSW z02ZRST|zgyS-E)mogV*3 zp?0mXeQtHbv2qqZVvk+@(lN9=3ebfTY0_0@Q_$y#>m^{9TOwqc@}I(M;fAXhD-_7t z<(p4`89y;?U`Cd?Nx=K^f)$zFnJE8nqx4FO_6LcesL&<;U^|a(G6I>gnSk?lyf8>6 zREFsdZ)6$~XQvSR=pc)X#&FW3s1?Cf0TF}D%LYb5Y83@*zk%;}Hbs@*z1t!qSQ2cJ2QGPr6>G36CfDZTSfnvO24NWaFP@fp6 z{=?_7OebbibR2cK!537O6r$BHTJrlV`Bg+z7Zj9)|9Jn^nI1Q5z5WBem3iC(=iQ^> zpI9D9DYw zwYrwxo(Lg5J-$!L{2=bDkX`-ufc1aIU$>K?|48i5M~O;XvrMIEh6nXN)H`}`Jq&p$ zm&dN*agqINgpvAi!#Qju=*bml552T=Ul^Vc^V+ zhd8iJ2>?Fvzs;f7M~fO&jt@#RKo$`Co_GT{H*b)*VER5AV!0dW<>r!fxzzVJ)v^XW zy!PYUy-meWtlHH^ofhZz+mC<9=$Dz$LKo`@_+Cq(^~gP0X{QYY_&iOr?+(xARX6s3G%#lst{`7dF^A#HK~!<`Wola-mpO8B+)rQBfn8efrBjcBRQWKniwJu?VhBI0yIMw)Xala%&A zwVC?;U@Oj|PI+)EY-D(toXGI8KVkP$IAIJ9OUMWD`CG`UJ~CwTlrxSuKj^f{@bxHtx~a+=HxXB zZniyzSUkby8F3s_?C>z9SNdcxdJ!XE{8;*9Lcac&%&6XyRb9$S#M4MVN;pTFcQFtZ z*?%V-lX^D^+2j$2+smJ{)bx!sA42jdtGY5;*c~`CZguJB6)cr()IN(zd$gVUbYF0Z zAose(`QK!V){FZwQfR%Z?U_`opKq?P>mg~4FG=KY#tDA(#Ry3LoHQ)u%4zp(<;t;2 z!|#Fk*dIHQ(EONQB|vsJNa43Px$RAemLWyH{rJ%iZ6bdx1Pf}u^(B=~&V@?n5ibc$ z3E%SuRTD+do+J+=$DeZ}Z6JsdZ;NKk85yB5koLl!anyzjUn?3`^~O>)%2c+ZcW zSdBMg?{E=w<0`K!>W>sAZTQJj6pkCHm%CH++`(Vod;CcQJq<5uuX+Vwfpya4d74k@ z`hA>-TEsg&&x@h?+HhrTKZwl#O1AR~@*WJFK>mBalV6&QJFYGgN=xI9;_<$B#0Qgu>O2 z>pu{niAzV*%OWc=%e0AAIA8CkJI?OJ>4g;udC^cuj>`-R=o(nU!pqTqNn=Sik^b(W z5X1@YL9QV8Dpqv2NK^m*JWNe=7xN&cGA9w=aHQK3L}XA zcX5QdBlP~`p%nX{l9Z+H;9oLdVDfR_2hDAh+$(!s`6}f<(1442PYlzUK5-Ei4r%wW zb?YL}G0e3%aw0Dqt>*2P$dc1F{1#;vBy1)yXX7rk%MQV#6>{ryF`#1B*!S9`sS;_~ z-7sl$5^P;p&G;osadO!XI@MbA@GZZw)j{)eOmNJWT%%A6sd%L8QU=i)Dy=WrFk9ve zTS~9TWxcGSRCd$}bhT#q@I^JK*)1~UYlUF{BtXHNsXbYV{5d|4zCS57*OB#*(Kezv zJ4GI?u}>OdSGM(XCHAftrZ-y?<5a{5S^Eq0d<~jnzwERPpxAzqlBiIMo^>*&=Esly zw#Lw<+oZtIJ@-%Fz+Q^sSRSZJ|3*zU+*Q^=)v9Z+Z>FoMn1*+=!_dSwI$-#VZqNUZ z%cmOlVRw?Z-2~`KLJn@y5=$@-$id#%5$Uw58Ts1pqefgyk3$hx^Ldzu{gfjl#KMhO z$)H*#SKm%&T5ya^C&#V2e5flw!ST;%UeeDN8kcX)Br~J21shm+u8rFKmlc-Gjl>`F zP<|}at@Wqvvl4kn3BFpv2MSBoz7C}CbnbruJ^KIAq>}+<0LtkZKz)ye?`mAz7npiX zOzL>J#HKeN*u;!O;)-;A$y}*=gQ`@VxlF)<+0wX}4XHFwqiWEmYpz_MI(-Snj~+}| zs@=CA5ITmVkoWH_zef91&yD`dMh!`8oDJ_|NBXUeHSmv(nWu{Qf*pcS(j0T zlbA7}DY>DuGmTz&&R$HOfhrX6VzDbzte?UKf;*jTi0-8LR^BS~`1z#tX{;vfQtOiO z-G4i#u<0{QM%x%EGL?N*?E#K6 z1GsC-`vMuDU)klg{==R9^tqxl( z;{rZeUbWM;4(DXVvM|#v@Ud`QhsjDRiX89<{`{Bh!|_Z*G9_GlZ&>w=;H+kp5ZHWpc#wIn?++JtG2>fGZnqC(Umt#5)C7pn(nUQv3CoGs;p@+^o3o* z#(%E2XPQD8=msN0xZXH;L)h$lVM`^TZ82p?$9&9CP`mpa|8%-_xtlF}p>uWf+j+nT^K}Vz z+0S~WC*eTqs#gsFGPL7Qg@*kTVrCGlz+3ax3CKH7_3VJjoAb%O=KY6!m8FIsf2_8M;Nxzt6Yv%1=5DK@N7r$!r6%DD0V{8JLe znaptoCdGyNTrTGG8cP-@?4yJ?#Xvau*$K#zY0kDWJrQ3cf*y}j8VkTe7x`D^h=g%d zLt9QDB2+(}WNbRyqyd3PUX!{ti;z-ldl+TOZGUxH0^Y)2t52~G>`aAU<+W|4`PAt7+&%`O-55K0R}r=EuDSQ?3R^}Cb=UsBxH7<6e*5sjQ;v@oRtfx z(SBn!4CuU&?pn-!+9u2F*LnSO8*;RZGMjIYnIpSC(s*FwbDc+iETXk%6&QazCY}72 z@{dnobEVCIadNT_I87LW4#RP6=OASYA{wA>0T4Ex)M0Q)J>1-Jiikf>`nXbD|EEc2 zB+oVhTOrX10S}>lPQrb>>+AadBiy>aF-Ac{+$4PdW(Q=6$kEYdJG395l@9HZmDJaH z0sg<1{belW&jZujgN9q6P*uTev3JCF$)&<9#ed$vFH)RMikwI}Btu`s2m|v0j9T$zqJojp8&FV2`4Goib}gI7Hz!0m z&p-Xm``e$}9-w)ah%l*}0v-XD6dEPzY(HZSti3R!Hu4P|F6X25EMCOkE#B;2SKf!N zFnbT6Wq;MmQgK#m8Wa8};EQ*P=tfse^~p(mr*N;XXmP;PObGGmhk4%)+jvTz(xj-* zvyP@o;I_0b_AB}lJ1nnEPb&%+0T$Fwfn2HN7tVeND{J^<|+p)K)+t061=7UGEW#|$JU?Qg8 z&%+H-vAzEG3OSg5`{09N4|k=ALZ06E(X@RxH}Sfn zEMef!+knt6F7HgQ-4hrA0La9;_eY6wPqNM_zR6?2x`tXFBF_o0{&ta&Hpw2}>%J5s zah#Bg4=W}MD-!7^qeIjwhm7947!2x7fo7iGF6a#4zetbuq1eC*>7%X_@KX)D!?Fi8 z*8mU({*G7Gxrf<|rNz7K^$23Dj#J?@>N z_9v@%Rj57iXfgi8yo3)`g!I1!BkULW~_wtBi>y;jD->(AI{8DJwH zHB*)3KW%-IqX^^YALqkWtj8ke88?QVl>g{2bFaDNCA#+Gk<^=L zxn~}VndO%^76+7)qE+F1ON;Hmhr2}y<=6j%o6&(E&);Fxzd8sobi*<1WiZ%<1=Vb1 zf~fZMj8!nX+-_Rn*FL7C2K|!$e4XCC8&bh>?SXI%W0r|{)tlN^^lTiK7@DQwR$r=m zf{VShf#Z6wu=AO=e@Mc#f}%}#U2odn-bN=pIO5qD1|r9b@;t&#EHHfiI{*>zFcEkc zIB|H@A%=Ff&8R8T2aqs}F$*o&a*8)(}C8Ip%XNOn5d@^unj{iJJL_K81 zKf!&?ZQ4MUSF;$Zu{N^SwaclrfA{>E$sCU~8hM=gfGdz_!K5(XJa*RJLA0ciDqrr% zWmLXZaaizJ$d#<71k4RKi8Vurtu8Z#qb9w<`9*A_*UpOsi|xD*Yuj@U71V?lRU6<&W4F- zX%u?Vz0X17WPBn6S~E2UQPJ{T`~U%PZOj>%<`~u>EoAn|Xv}3C%;#CSywS6z`*;tc z%B>lSMiz!qULs3yCAdYwwXv2SMS=QyMqu)q2_zj?jqWlJWS@Y>f z3hY>eUlLa>l}vHrq&K^=LH||}xqMJc7uG(!H#dpb>PRfYG+)X+8RD8@mX^HDvQ7Cg zabsw4sgUxd8+6t_q07S45dw^@X z9xxdPr<$)lABeMecfo@#))!@R?mPZ!zw9Lu-gJj8ornHeGdY4q17t}-sn~NW#QLcx zr8>ql@F~O$(70-Rr}Xsxf&kb|^7T)z<2;S@6#TVCeJ}ulS?1#RGYQ8JZZd?`r*wqf z3~8xH30UL5szv6Z!mx#~pCj1 z>*6a>UP4dV`!q+dB!pia(Zz@WI@3Dz_jqEUr~8Z%tcRybUSbjZ<%{wQGF7UZ)ocdQ z>3Y>48>KV)l2x>H^T{#~7?L0402%?08Jj4@NXg)R=~)uS1u2%npCO{SXmVhBDpO%5 zLM+F<0@k(T?ysDhSqpo_Q&=R{tI;h} zzz-&)Y}QUe7`V-N`Ooy9x%hw!E>wK?x};jas;P~M)MU8i#k6PL1HY$hUuU8gPr)+f2h98&#wdn?wTCAI0EWw;-;IT5(|!6yIXMG%VANA z%w-V_VsE4D%nrEkLnr1p%2w4S{<==&euiP!ux#!R{gKfUoBh;2@Y58A)GBJkFjyP6E4)ar{u%eUgl1k1t`N> znN_eA9^Au}f-3ounYj07^#T8+&EOz=c*@Jb2W0Rpm#!0HA_9|r?7yo+ydAC8|07$07Wk2H9wPsJ6yXRu*LAM7Xa~3y>Npl)5 zUDfBPp|6UzGwP`hAK>i}uNOAUCk*yiqaF+w`7`PfBo#mA;A~b@yBU|`p|_&3((bb>d_NC-d2@TWKG1uiJPEW^c{+i@Q~wvd1NUamBv9O+9U53qpK-=^&!HhWS;3H8n6;pA9d6;1 zfQRziyR3t$d|`)0{ur;|ub$?4i9bw3Z7`DAmgP-l@E6LZiI|v!u(>WZDAey`R05Or*tYT6e+M_q9LHDIkfPf(X-@l4^2l|k*dpg6$ZCfQFkF` zK1F+^M@biX)W83)Y*8x1(eM@vCsk`{;`9t&$#IW25@=k^wfGV0*hgVKOYlbUQ|7{e z^{}+femWLkFbQhVS?YRFGbWB3zqpXOpT`fU2uMSzG(}H7+y;SK3!V(QKaeAW6S3E1P?Y^Px<|_rsr<8v@H8+p`mf)+ zdq(+R^-~YnDArSE?LEOoB~7ACCiMa_+A`w&cPP&LcQN$eXkR)ff}C8=zN}+P7)Kf@ z6<~usZ4$d-&0=s{O};pxhNuV0V|Tl<*^kXa=@u}EH!8z^eOgj5PHz&S9^Lt>m&_wR zX~2$wbGZuRN;n9%KFE=IPrdse3%xgR63>PS_`r1}`yW zfY4RmS37^?M>IDGwIun^mv)giDE(_)E_m8ePu6kw3|S&-NCGwUbgdvh_9xDuetSDI zHt<^t>|gzSESrv`-j-tn_X(WQii5wdt(_P>hvxOAAHL%6muyGbC~b8T(-8ST6c&!3 zVeMXw`RksIwP_aSpvL{sYdET1WWdz`Lx0ZgC&UrG_UL45m*DiOwak_+L7Xyo81dpa8mi_FPqk@VZrqtCGpxC(SRik$N!tB;ies%Cjv3%XC zX{CX>lFI%YTu4WToDT~9b*}moQUaGbtk$R5DyRbHmxcxJ|Dgw3G$gUw?d(p~IulO? z0&6FGXuKn^iKQipND^Us0SjtXq4~8h!rK2qjq)yD48&x_fQ^&Miid2SZ=qCd!B`X9 zgoW%x+Y+V`+O>8pwlLkjTV7C`tR4N8Af;eo%T~>(Kgcsiou!=DD_zIIW5Cbxr#42y@4w{yV;vuQ3rLooxL>LXw`pH4Nbe4vYw0&I4ioAGy$fV-ibBc?C34 zbh1fVRDah=z8tF-=ZLn^)Zq`p;&nOn3FEmBVY{{lt3dqE)UVwAm2WsQm|u5mDejTf&Ti=KI&2|vQ>vo9Bj z&iS|&)^r#`F$G=O+I?MtqY73^Y`PuONTEaY*KA)*waf3&pttzf@X*R=dn^oIU{Ua4 zL~MH()}H$wXKC=W%J*hm?Q(+Uz{iMfzZ(|=Ey92lD|=7H#LRWXe|tRqEGp`b51Fc$ zk%nD&wA`dQIY6jcthKr1XXWpWWShFhmh@mmR>SB!$n)e;*-HC<$hNmjis7L!jvFooh$ z%1Q`N3Bl2djKOT)s!f?rFrrU}l8(~?PV97#FwDzkLOJd~XAFb?_}H@Zg~2+8)n)Rw z*6C=ybw6_zFk=G4;gF2cTX2<(CyIiI_Bv^-%t4>G{XCn($vQIg60V%yzL23*OG|2k zP@zXjiju$k7RmC%vI77rY~-6>PdMlAwgD#!SEP0Kvk$_+ldGQ*eK!RibN4bYJU;vG zwrxXMQ+e7av(Qi;?d-Iory{pVPKBDus)*qB#1G;3)1KdpGUH=?nxYMkk0NqAG{kFR zn5;;VA+Z=5Jcwnq?nvgQG`t3G+UxCcv1l$v?llwv@w3fidR`|&j$|!E8An+t=%F5? z8j*s0U<$6>_~3qd*#>n-A6>OZ>nplD)1;0QrV4LmrwTZlnVt9O2pf#?2n#ZwQj;zX za#u7@P%1Z@5AhHQ``vD(bE>Lq5m8YiEM>Y8p;J$5+0D=;E{6!a{%Jub{NM`tr67Yo zDrM$An>235}_676e&|Is+W;dV5y( z?_%h|Kj2taca4N>yAdIloxAWC>dhn%t6SlyG;K%Y#dL|P8t^V*)O&nIpzbZ za{4L{cJ;n4jk6o&-^~eOHI!ka?dDY&H$iv`R=gfHpO+NzRe^qFh@igLU)i4MqOQ`} zqDJmu+sKfIiTO{ZLG_k!77>Su=H9|ik<@myKaCl{^K!IuJbT4))LRtKy#9imp@x=| z@5nh(L+MW-e~G&!1tA|A=Vz=)oU^1Y!36 zz9Ef3M#mU^Y3<5G6Yr0ds97u$fAp8bna_@v&DDbm>I{&IV5s%fX{m?A*D?oWkrS!6 zvC*hsKglCQ-pYCp35_*%&NMsDz5|}m5B}h;YYd6x*n_c<1VD9*0<^czCq2r%RL-$;%?B!1@*6v2a*Zoz#}99sWrM%FiZ>0QyICqfGU59 zT;SiMcsLWnQ!E@vp`+ebmI7Bq==EPDbscB8NVvpN(eFq&5`xV`>vzncX>5r5D$+0%w*0NS=6u24B35B5!bk^E*IMG^hmeg*mES$E0Y%m>~JW*l^$+T6z4@CWisS)Pyl>EB`fZ4kM0PLr70QtJ8--dA-$z*^K~NL@-n5NS z_IPk ze!P1QebL(9dKqR8K)xls1inG#SH{W+;$j0A4cFLY#Iy1?`BB7?S6}7^zFN%(AiX}^ z(*nCYj+P%?@w9~ksqd8XrXDO%J^uaR*oEQ0U4Wf)332QOlP>m25n=Vy14iwJ5&alI zi*wYK3}itsSOqa668L51M??2$*r8ZHaZe=rZs(pc0H&3@q@vzPR9~*A*=OZ+YYm>} ziEh5`Q@%x~9I>)FJWiuE8#lA#v3W*N^g=#V=H@9tRf35pg=wtM2xR)J8^IfWcWIcj z>}^fPJAEA?s{Tt9&GiT;!RD@+8BQdHV~rNFo=FVnBXQI>dAkya>59dAg8>ly!*`xB zr~34BV(#a?t5}Ts)X%ALgz%7j8|8_lLxJRd?qF zN?6MgQgcJ877yd8maX0~S0}_7f1P87P_@IhUmcyQW8;1>d=DmPWZ%PaM{T1T%kl2} zGzI#@0zqUa3S?`4AiFNh9+Jf=0Ck~n?Z?7 z#~=Ro3P4|LAOfJjsqgcy0pFTMz1PI2$PYEh%#vD*T$Kcst?-++Vj2bPj+U=$?*v6c zZ`-$ec)b_j{f_@GHqp8VK%LVP7)461U&dl`KwCye-!h*ijryeV7@JIknN)2eylipC z|G=*@9eICpB=b<0K*8mL4sSLe$=0&;#fwU^7@3{Cn$@#5Cmnh{j&IJ=h4hT$evmtH3P z`8?+SR@S?4uF!aV(SkO=EG>y^ev;Yr+Pj@Cq`zRA_IGgh7!9mi+doV;P3BMR0GwV0wJ4ajY#6YKSj$iq!CtLnFXMcNGP?^(!F0`v56KIYy=ki4( zZYxdp#cR3}csc=+EVcut_tOFnhsjk&C{_e^z&~EGc0U`6p&~pJU6iL!UUhko89hXs zim-3i?CAfvNU0IqCx(mkd5Y zY@cYOB4f^l-4;_mVw1Xx2fUl?=X!7;NFS)X4=2S;1>pe-5Wq^ojzT7z4qwV%HWmQD zVN9q7bg^G6BgM%|XNLtzcjB>AtXH_n3@tNJzb~q}fTWLsuBOfsB(DvNi53nwfO+_zRiJ=*aN8O&-#->3C;TQ-%GcWf zq&)VqCZPj8baZ(W_;P*TVqL*dAYDRy>fwf@{ z0@M;i@Wl-Obz+MBL;!CbiW>O>wRo2)Qc;`vb8lD=;4aEAR)A_ELJ}PI)V1df4*yb83Oyr9j$GeTD; zyNbFki&R*Z(v9lP4QTmHobda`mMH2^W!0GB9NB=;eEC3Bfr~7%} z=?5^aQYf&e&kyod0$W`Ly?7cqJv@h!&%H5irN4BLl;U$$kLqCa#NZ|fq!Wiv9ElB62)0c~zLWU7pmenqGEZ>a1ZN6h-50vu&?@Plz zra2hWydgC(5eBC?zq@-=1U&xTNd3wqF4Oa#k+~=t%)z>`D27`;-11TL|2$yVeo0y! zi1d-u&>nM>Xy=7MJU0*-SYXd}M1)+8lfeRxpz{L`LpMbu3h5Tqp*jk(lWLP2Hvx8| zXN+6K99f69RLPop+MKHf%x%}}HVNKCfJL!`$Qi9IAHHqw?EYdO%P!={;)zT`4IiVr z2YL1P*|N%Y(rxsG3Od*V;-`BD_SRLOf5ijhN*ybr2l?hdrTfFr5^>pBEf`;1VbTgk zX9))Df^{CDSpYWY&a3->c=&jD&HF*?#2oqtYeZLIn`!k?I)dnsjZ?gw!5u~xO$5GA z9eo8>!agN$fx2z`IRGGSjf<4gh>_`|%G1c!4A_2I^zMz?;fCV<$1DLC(S!K4=oscS zE=27xunlhdz$Q2rby^jl1HT|qCgF1r1%Te0MJ3u80jfp4J}6e>dU<3UA&S=ZfFFI; z$2Tw9H9zb&QOM<%K0o4yg5Lz+C-O#nG0ume|9ydoQt|!20AdTB^!AxC2G^xsMNwZ5 zDyv+c0UIyOg1xpXoH2@A01_Ah)+G8+;3je%GXZi;#KcM+Tl2oO0t7|8aE3Z?BPh2H z6a4JB5#$*H^_Tg#KgYj4m45~J;=kcv0)V`F*aQ`wg^z!ud3=bA-y|%8SvdjTfEX-! zdR;0&XoOTHLDZ;H;SnNfI=0KKz;1m+Df;ehlsdk61W;e^!w=>kFaEpyYXD&VFDK{l zeI9%Mssa3MNdJ7o-#4BY|9?DnHUah265zo1&ar-!r? zVRX1#Gw_PeASuzNTyLsj5S8wdQ3?eJ^!R5}x=|m}z4-sO{C9p4NLk49?9A`p1%L;E zKtnm!JQ{z{kT_)gKFd}x#)Ut#Ko;g8daylYoI z%U)H~DX0kACFR9`obR%lpU3XS1NUO!-iH8% z9d+-E|L?}X1^@u9dGpbo0brh8nEj_5K7wj4?FojkU62MrNjhgy>a>+X8jV^puWDKx zYmU{%tsV?gOJmodZ>s;r`goAgacKbqfR9^Q-_(o$Z^yrG0>b2^c9~1ulbefS&d{U4 zwdnWoDOWq(t{BSvrS1*5!50xP$CrIi~sM(zi9x_V+ioxr`fv{;pPnEQvhn^88EnykA^RR#DP9n z87R?8CDAahq#OE`VDnz(CqT+1^AJ5A0Aw1Y#~3{!j?s5<5n$iFHg@mt1AOuS?f8GV z2?)T?&ca+`+|0V0fYGdO0)E@m5U=z~|Is8ffZiimI1fX}|7-7TcN^t_D2z6O=orF} zcHj5@FLjqLQV2_Q+O49o4W|5yK3TGgT%ITOiOD{Q$@ zNkN4<%QNenM>N74o@c=`FFXrtI7h%Yjtxhf8l1gy#bUEG>$C~6fzi1dt8TPr4bSHI z6EXXA+717g!#`aDXy@!iU&lA?YzyOeQt0QlEtt-ZJvB3N5SVlmZUwQBo~vncl4*ea zvn&+PhLgWEk&vb-SPSMzur6?9512$Ts`%$+ZTP<){>i5R;z31@=Z?~xxc!}_9H1?1Qp%!KI>o@D%`(OY9sO@pa?GKO_;Jqq z*UDSR-%<=*4gXif9}R%3KFMwz6xS<~AWK7g(u!6(tMbh6Wr&rJE#O#tI}NT~(dy1_5!>6MH}Zj083 z4ZK!;OVPMzsLKF-Uk^~JjXEPU?)ubi&{nsnN(bcT<*fv0d#QfI|8)4r2EcVwHkMS` zbS=}RS@|~C6?AF#PQTJubd@-(=_-js(EVoZva#yAx}$cvt%m<0@Q)2(M_$r6N@Mv; z!^RwEw=ZskE{9^m#z&6ZS6pPxB@5K@#B~d*@Z(Fe7yy4UV zQseV#S(||p7kAFVa$$xQbg@uDLhKA1{)fPyPXJD0tK@i@hGnPy>37+fWpV|qu`1wV zo^3k)L|wi}RyT{@CGD$IgFFVPgx67ox#TuEg1X>guXd`Im+H*j$Ri_+Ad(bRUBmwn z_~Qvc;t~JSZMqE7FwB=>L##|*78;^m^%Y_q+wM_NS5SAMIVre>dMeq~tSk}LMASKn zkoz|B9MwJP`b1Il91^yO59+WDUi|){dPna$fKo)f;eQDHcYX)JhoCZ*%dp%`H$U%` z$pTO^gHK2#L9?zAcB}=7|5ZT}uK9eD8Z`t>1Xwdiy1#;(u|y+xC(hIZI z67qKWcRaW*vs~RW$pbs^DE;#i_HW57{@p|n2_~@nV2DN0keMN1Azo`(1_?0wbyP7V zr^c_(6zSAoFogdUhdnx_75ugh(L;mNEOW#E82DHJ9e8+upD&|Se!q97GPQsGZPe)X zDQ^H4DbvvD?M;;ikS(OpHB&J&1ra!~0ENI5MFbb@>Ug3p`To~C4iZdWgQ!LagygO;Y{I=Z!6hxa37pvQEGw2xW$|)B(Q!8cWJt= zM`lepmXGP$skKs*o$?y<{I9&)IsRrg{11UY8bFn_{{*0_PJK>F)m1U_tw_EeV8T=- z7%(3m;3FzSsvBn+TM05s8Eu6dF%Lh4gX`{9~*$eS|l7M0Q(#XL1UE5CnJh`1Pcz8 zBMR^%&?In6aAW~yX3I&G(nIpJd|p(gAdn|<8Qbtb9sYYu04;=l8h6eg_nqq`nWxSp zG(0GZP0S{IZvzhOGee=jOSWyTjUyg8;WC@!kuBJjyR;pf<8p^;v!b-;pqR5(rg&Hc zGvTqd9x0la19YJp{-?vA4PYygl8;pQNeP)w0F4?oIt%sJtpPM@)abO-8bG5)C#Kc_8Z|mGwFc0r z(TV9;4WPe16ZOmM0C~I)Jy+dc0{`y5aPrx@g&*)#(Zv+8dOmdS&a}?rbi@DL_;;M_ z`}=)<==6i4YS%xciv0rs=${72-tP~J;PKz}{r6m$)9`t6$z zzQ+IQpHTf5?e))A(}w?#~LPswqfOTWC2{a=15^U#&D uO!Z^=5bbV@?6A(w<#w(ofJTj8kp2L%`k_e*5@ _Note: this tutorial uses examples of static content stored in YAML files, but similar methods can be used for Markdown files._ + +## Getting started + +Image optimization in Gatsby is provided by a plugin called `gatsby-image` which is incredibly performant. + +### Step 1 + +Start by using npm to install the `gatsby-image` plugin and its associated dependencies. + +```bash +npm install gatsby-image gatsby-transformer-sharp gatsby-plugin-sharp +``` + +### Step 2 + +Add the newly installed plugins to your `gatsby-config.js` file. The config file ends up looking like this (other plugins already in use have been removed from this snippet for simplicity). + +> _Note: once `gatsby-image` has been installed, it does not need to be included in the `gatsby-config.js` file._ + +```javascript:title=gatsby-config.js +plugins: [`gatsby-transformer-sharp`, `gatsby-plugin-sharp`] +``` + +## Gatsby-image configuration + +Now you're set up to use `gatsby-image`. + +### Step 3 + +Determine where your image files are located. In this example they're in `src/data`. + +If you haven't already, make sure that your project is set up to see content inside that directory. That means doing two things: + +1. Install `gatsby-source-filesystem`. Note: If you created your project using `gatsby new `, this first step is already done for you. + +```bash +npm install gatsby-source-filesystem +``` + +2. The next step is to make sure your `gatsby-config.js` file specifies the correct folder. In this example it would look like this: + +```javascript:title=gatsby-config.js +plugins: [ + `gatsby-transformer-sharp`, + `gatsby-plugin-sharp`, + { resolve: `gatsby-source-filesystem`, options: { path: `./src/data/` }, +] +``` + +Now you're ready to start working with `gatsby-image`! + +## Step 4 + +The next step can vary depending on what you're trying to accomplish. + +## Querying data for a single image + +Use `graphql` to query an image file directly. You can include the relative path to the image file and determine how you want `gatsby-image` to process the file. + +```jsx:title=src/pages/index.js +export const query = graphql` + query { + file(relativePath: { eq: "headers/headshot.jpg" }) { + childImageSharp { + fixed(width: 125, height: 125) { + ...GatsbyImageSharpFixed + } + } + } + } +` +``` + +There are a couple of things to note here. + +### Relative image paths and `gatsby-config.js` + +You might expect the relative path to be relative to the file the code sits in, in this case that's index.js. However, that doesn't work. The relative path is actually based on the line of code you put in the `gatsby-source-filesystem` config, which points to `src/data`. + +### Image fragments + +Another thing to note about this query is how it uses the fragment `GatsbyImageSharpFixed` to return a fixed width and height image. You could also use the fragment `GatsbyImageSharpFluid` which produces scalable images that fill their container instead of fitting specific dimensions. In `gatsby-image`, _fluid_ images are meant for images that don’t have a finite size depending on the screen, where as other images are _fixed_. + +The query will return a processed image at the highest depth. That is, the deepest part of the return object. The returned result will be automatically passed into the component and attached to the `data` prop. You can then display the image using JSX to automatically output responsive, highly performant HTML. + +To display the image, start by importing the component provided by `gatsby-image`. + +```jsx +import Img from "gatsby-image" +``` + +Now you can use it. Note that the key for pointing to the image corresponds to the way in which the image was processed. In this example that is `fixed`. + +```jsx +headshot +``` + +Here is the query and usage all put together: + +```jsx:title=src/pages/index.js +import React from "react" +import { graphql } from "gatsby" +import Img from "gatsby-image" +import Layout from "../components/layout" + +const HomePage = ({ data }) => { + return ( + + headshot + + ) +} + +export const query = graphql` + query { + file(relativePath: { eq: "headers/headshot.jpg" }) { + childImageSharp { + fixed(width: 125, height: 125) { + ...GatsbyImageSharpFixed + } + } + } + } +` +export default HomePage +``` + +## Querying for multiple images from YAML data + +Another way to source images is through YAML (or Markdown). This example uses the `gatsby-transformer-yaml` plugin to query the YAML files. More information about that plugin can be found in the [Gatsby plugin library](https://www.gatsbyjs.org/packages/gatsby-transformer-yaml/?=gatsby-transformer-yaml). + +Here's an example of a query from a list of conferences in a YAML file: + +```graphql +{ + allSpeakingYaml { + edges { + node { + conference + year + } + } + } +} +``` + +In this case the query starts with `allSpeakingYaml` to direct `graphql` to look for this data in the `speaking.yaml` file in your `src/data` folder referenced in `gatsby-config.js`. If you want to query a file named `blog.yaml`, for example, you'd start the query with `allBlogYaml`. + +### Troubleshooting queries + +A common error you might run into is `Unknown field allSpeakingYaml on type Query`, where `allSpeakingYaml` is replaced with something specific to your code. What the error boils down to is that `graphql` is unable to find a matching result. This can mean it couldn't find a file that matched the first line, meaning that no `speaking.yaml` file exists. +This "Unknown field" error can also be triggered by finding the file but not the associated content structure the query asks for. +Yet another way to find this error is by leaving out the `gatsby-source-filesystem` plugin; without it, the folder that holds the data is not visible to `graphql` and it will throw the same error. + +## Rendering images sourced from YAML + +In order to reference your images in YAML make sure that the relative paths are accurate. The path to each image should be relative to the location of the `.yaml` file pointing to it. And all of these files need to be in a directory visible to the `gatsby-source-filesystem` plugin configured in `gatsby-config.js`. + +The inside of the YAML file would look something like this: + +``` +- image: speaking/kcdc.jpg +``` + +Now, you can create the query. Similar to the single use example above, you can use `gatsby-image` features inside the query. When the query runs, the relative path will point to the location of the image file and the resulting query processes the file as an image for display. + +```graphql +{ + allSpeakingYaml { + edges { + node { + image { + childImageSharp { + fluid { + ...GatsbyImageSharpFluid + } + } + } + } + } + } +} +``` + +Since the images are stored as part of an array, they can be accessed using the JavaScript `map` function in JSX. As with the single image example, the actual processed image is at the `...GatsbyImageSharpFluid` level in the returned data structure. + +```jsx +{node.conference} +``` + +## Using Static Query + +If your query is part of a reusable component you may want to use a Static Query hook. The code necessary to do this is almost the same as the single image use case above. + +```javascript:title=src/components/header-image.js +export default () => { + const data = useStaticQuery(graphql` + query { + file(relativePath: { eq: "headers/default.jpg" }) { + childImageSharp { + fixed(width: 125, height: 125) { + ...GatsbyImageSharpFixed + } + } + } + } + `) + + return +} +``` + +Instead of a query constant and data that references the result like in the first section above, you can put the `useStaticQuery` hook directly in the JSX code and then reference it in the `Img` component. Note that the query language didn’t change and neither did the `Img` tag syntax; the only change was the location of the query and the usage of the `useStaticQuery` function to wrap it. + +## Multiple queries and aliasing + +The last use case you may come across is how to handle a situation where you have multiple queries in the same file/page. + +This example is attempting to query for all the data in `speaking.yaml` and the direct file query in our first example. In order to do this you want to use aliasing in GraphQL. + +The first thing to know is that an alias is assigning a name to a query. The second thing to know is that aliases are optional, but they can make your life easier! Below is an example. + +```graphql +talks: allSpeakingYaml { + edges { + node { + image { + childImageSharp { + fluid { + ...GatsbyImageSharpFluid + } + } + } + } + } + } +} +``` + +When you do that, you’ve changed the reference to the query object available in your JSX code. While it was previously referenced as this: + +```jsx +{data.allSpeakingYaml.edges.map(({ node }) => ()) +``` + +Giving it an alias does not add a level of complexity to the response object, it just replaces it. So you end up with the same structure, referenced like this (note the alias `talks` in place of the longer `allSpeakingYaml`): + +```jsx +{data.talks.edges.map(({ node }) => ()) +``` + +The top-level object name of `data` is implicit. This is important because when you conduct multiple queries as part of a single component, Gatsby still passes the entire result to the component. + +Here's an example of data flowing into a component: + +```jsx +const SpeakingPage = ({ data}) => {}) +``` + +Everything else gets referenced from that top-level return name. + +With that understanding, you can combine two queries referencing images and use aliasing to distinguish between them. + +```graphql +{ + allSpeakingYaml { + edges { + node { + image { + childImageSharp { + fluid { + ...GatsbyImageSharpFluid + } + } + } + } + } + } + banner: file(relativePath: { eq: "headers/default.jpg" }) { + childImageSharp { + fluid { + ...GatsbyImageSharpFluid + } + } + } +} +``` + +Notice that this example uses aliasing for one query and not the other. This is allowed; there is no requirement that all your queries use aliasing. In this case, the JSX would look like this to access the `speaking.yaml` content. + +```jsx +{data.allSpeakingYaml.edges.map(({ node }) => ()) +``` + +And then like this to access the image using the alias name `banner`. + +```jsx + +``` + +These examples should handle a fair number of use cases. A couple bonus things: + +## Aspect ratio + +`gatsby-image` has a feature that gives you the ability to set an aspect ratio to constrain image proportions. This can be used for fixed or fluid processed images; it doesn't matter. + +```jsx + +``` + +This example uses the `sizes` option on the `Img` component to specify the `aspectRatio` option along with the fluid image data. This processing is made possible by `gatsby-plugin-sharp`. + +## Bonus Error + +Now for errors to watch out for. If you change your image processing from `fixed` to `fluid` you may see this error. + +![In image cache error message.](./ErrorMessage.png) + +Despite its appearance, solving this doesn't actually require flushing any kind of cache. In reality, it has to do with incompatible references. You likely triggered it because you changed the query to process the image as `fluid` but the JSX key was still set to `fixed`, or visa versa. + +## The end + +So that's it. This post included a number of different possible use cases, so don't feel as if you need to explore them all. Pick the examples and tips that apply to your implementation. + +## Other resources + +- [Gatsby Image API docs](/docs/gatsby-image/) +- [Using Gatsby Image](/docs/using-gatsby-image/) +- [Other image and media techniques in Gatsby](/docs/images-and-files/) From 2d742aa166f5dd24490e3768c2985a82ba2272d2 Mon Sep 17 00:00:00 2001 From: LB Date: Wed, 10 Jul 2019 09:24:16 -0400 Subject: [PATCH 03/11] Update docs/tutorial/gatsby-image-tutorial/gatsby-image-tutorial.md Co-Authored-By: Marcy Sutton --- docs/tutorial/gatsby-image-tutorial/gatsby-image-tutorial.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tutorial/gatsby-image-tutorial/gatsby-image-tutorial.md b/docs/tutorial/gatsby-image-tutorial/gatsby-image-tutorial.md index 069ff66f754ed..28a7b7fcecf12 100644 --- a/docs/tutorial/gatsby-image-tutorial/gatsby-image-tutorial.md +++ b/docs/tutorial/gatsby-image-tutorial/gatsby-image-tutorial.md @@ -51,7 +51,7 @@ Determine where your image files are located. In this example they're in `src/da If you haven't already, make sure that your project is set up to see content inside that directory. That means doing two things: -1. Install `gatsby-source-filesystem`. Note: If you created your project using `gatsby new `, this first step is already done for you. +1. Install `gatsby-source-filesystem`. Note: If you created your project using `gatsby new `, this first step should already be done for you via the default starter. ```bash npm install gatsby-source-filesystem From b967d1a916ca9633e203ae4b60ede267d80e54d7 Mon Sep 17 00:00:00 2001 From: LB Date: Wed, 10 Jul 2019 09:24:50 -0400 Subject: [PATCH 04/11] Update docs/tutorial/gatsby-image-tutorial/gatsby-image-tutorial.md Co-Authored-By: Marcy Sutton --- docs/tutorial/gatsby-image-tutorial/gatsby-image-tutorial.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tutorial/gatsby-image-tutorial/gatsby-image-tutorial.md b/docs/tutorial/gatsby-image-tutorial/gatsby-image-tutorial.md index 28a7b7fcecf12..20328608f0efb 100644 --- a/docs/tutorial/gatsby-image-tutorial/gatsby-image-tutorial.md +++ b/docs/tutorial/gatsby-image-tutorial/gatsby-image-tutorial.md @@ -101,7 +101,7 @@ You might expect the relative path to be relative to the file the code sits in, Another thing to note about this query is how it uses the fragment `GatsbyImageSharpFixed` to return a fixed width and height image. You could also use the fragment `GatsbyImageSharpFluid` which produces scalable images that fill their container instead of fitting specific dimensions. In `gatsby-image`, _fluid_ images are meant for images that don’t have a finite size depending on the screen, where as other images are _fixed_. -The query will return a processed image at the highest depth. That is, the deepest part of the return object. The returned result will be automatically passed into the component and attached to the `data` prop. You can then display the image using JSX to automatically output responsive, highly performant HTML. +The query will return a data object including the processed image in a format usable by the `gatsby-image` component. The returned result will be automatically passed into the component and attached to the `data` prop. You can then display the image using JSX to automatically output responsive, highly performant HTML. To display the image, start by importing the component provided by `gatsby-image`. From c80ef99cce44705f6bb7924943881b5485558a05 Mon Sep 17 00:00:00 2001 From: LB Date: Wed, 10 Jul 2019 09:24:59 -0400 Subject: [PATCH 05/11] Update docs/tutorial/gatsby-image-tutorial/gatsby-image-tutorial.md Co-Authored-By: Marcy Sutton --- docs/tutorial/gatsby-image-tutorial/gatsby-image-tutorial.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tutorial/gatsby-image-tutorial/gatsby-image-tutorial.md b/docs/tutorial/gatsby-image-tutorial/gatsby-image-tutorial.md index 20328608f0efb..62f96116a7f8c 100644 --- a/docs/tutorial/gatsby-image-tutorial/gatsby-image-tutorial.md +++ b/docs/tutorial/gatsby-image-tutorial/gatsby-image-tutorial.md @@ -133,7 +133,7 @@ const HomePage = ({ data }) => { headshot ) From 79847739e261d8bb0593938b35e20b3391b4a308 Mon Sep 17 00:00:00 2001 From: LB Date: Wed, 10 Jul 2019 09:25:22 -0400 Subject: [PATCH 06/11] Update docs/tutorial/gatsby-image-tutorial/gatsby-image-tutorial.md Co-Authored-By: Marcy Sutton --- docs/tutorial/gatsby-image-tutorial/gatsby-image-tutorial.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tutorial/gatsby-image-tutorial/gatsby-image-tutorial.md b/docs/tutorial/gatsby-image-tutorial/gatsby-image-tutorial.md index 62f96116a7f8c..86c477ae4b518 100644 --- a/docs/tutorial/gatsby-image-tutorial/gatsby-image-tutorial.md +++ b/docs/tutorial/gatsby-image-tutorial/gatsby-image-tutorial.md @@ -155,7 +155,7 @@ export default HomePage ## Querying for multiple images from YAML data -Another way to source images is through YAML (or Markdown). This example uses the `gatsby-transformer-yaml` plugin to query the YAML files. More information about that plugin can be found in the [Gatsby plugin library](https://www.gatsbyjs.org/packages/gatsby-transformer-yaml/?=gatsby-transformer-yaml). +Another way to source images is through YAML (or Markdown). This example uses the `gatsby-transformer-yaml` plugin to query the YAML files. More information about that plugin can be found in the [Gatsby plugin library](/packages/gatsby-transformer-yaml/?=gatsby-transformer-yaml). Here's an example of a query from a list of conferences in a YAML file: From f9d92b9e064122f1fbb226ec16e2388d04ec9a85 Mon Sep 17 00:00:00 2001 From: LB Date: Wed, 10 Jul 2019 09:25:38 -0400 Subject: [PATCH 07/11] Update docs/tutorial/gatsby-image-tutorial/gatsby-image-tutorial.md Co-Authored-By: Marcy Sutton --- docs/tutorial/gatsby-image-tutorial/gatsby-image-tutorial.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tutorial/gatsby-image-tutorial/gatsby-image-tutorial.md b/docs/tutorial/gatsby-image-tutorial/gatsby-image-tutorial.md index 86c477ae4b518..6731570ed3f00 100644 --- a/docs/tutorial/gatsby-image-tutorial/gatsby-image-tutorial.md +++ b/docs/tutorial/gatsby-image-tutorial/gatsby-image-tutorial.md @@ -157,7 +157,7 @@ export default HomePage Another way to source images is through YAML (or Markdown). This example uses the `gatsby-transformer-yaml` plugin to query the YAML files. More information about that plugin can be found in the [Gatsby plugin library](/packages/gatsby-transformer-yaml/?=gatsby-transformer-yaml). -Here's an example of a query from a list of conferences in a YAML file: +Here's an example of a query from a list of conferences in a YAML file with an image for each one: ```graphql { From 6b7e11d364928a2b3fbf0351f3cffb8d3929bd2b Mon Sep 17 00:00:00 2001 From: LB Date: Wed, 10 Jul 2019 09:25:56 -0400 Subject: [PATCH 08/11] Update docs/tutorial/gatsby-image-tutorial/gatsby-image-tutorial.md Co-Authored-By: Marcy Sutton --- .../gatsby-image-tutorial/gatsby-image-tutorial.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/tutorial/gatsby-image-tutorial/gatsby-image-tutorial.md b/docs/tutorial/gatsby-image-tutorial/gatsby-image-tutorial.md index 6731570ed3f00..f8e0df11dfa9c 100644 --- a/docs/tutorial/gatsby-image-tutorial/gatsby-image-tutorial.md +++ b/docs/tutorial/gatsby-image-tutorial/gatsby-image-tutorial.md @@ -166,6 +166,13 @@ Here's an example of a query from a list of conferences in a YAML file with an i node { conference year + image { + childImageSharp { + fluid { + ...GatsbyImageSharpFluid + } + } + } } } } From 8632d20eb461fd1641a0defcc1342cfec5aad50a Mon Sep 17 00:00:00 2001 From: laurie Date: Wed, 10 Jul 2019 09:57:11 -0400 Subject: [PATCH 09/11] addressing comments and feedback --- .../gatsby-image-tutorial.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/tutorial/gatsby-image-tutorial/gatsby-image-tutorial.md b/docs/tutorial/gatsby-image-tutorial/gatsby-image-tutorial.md index f8e0df11dfa9c..96fb257b956e5 100644 --- a/docs/tutorial/gatsby-image-tutorial/gatsby-image-tutorial.md +++ b/docs/tutorial/gatsby-image-tutorial/gatsby-image-tutorial.md @@ -181,12 +181,6 @@ Here's an example of a query from a list of conferences in a YAML file with an i In this case the query starts with `allSpeakingYaml` to direct `graphql` to look for this data in the `speaking.yaml` file in your `src/data` folder referenced in `gatsby-config.js`. If you want to query a file named `blog.yaml`, for example, you'd start the query with `allBlogYaml`. -### Troubleshooting queries - -A common error you might run into is `Unknown field allSpeakingYaml on type Query`, where `allSpeakingYaml` is replaced with something specific to your code. What the error boils down to is that `graphql` is unable to find a matching result. This can mean it couldn't find a file that matched the first line, meaning that no `speaking.yaml` file exists. -This "Unknown field" error can also be triggered by finding the file but not the associated content structure the query asks for. -Yet another way to find this error is by leaving out the `gatsby-source-filesystem` plugin; without it, the folder that holds the data is not visible to `graphql` and it will throw the same error. - ## Rendering images sourced from YAML In order to reference your images in YAML make sure that the relative paths are accurate. The path to each image should be relative to the location of the `.yaml` file pointing to it. And all of these files need to be in a directory visible to the `gatsby-source-filesystem` plugin configured in `gatsby-config.js`. @@ -279,13 +273,17 @@ talks: allSpeakingYaml { When you do that, you’ve changed the reference to the query object available in your JSX code. While it was previously referenced as this: ```jsx -{data.allSpeakingYaml.edges.map(({ node }) => ()) +{data.allSpeakingYaml.edges.map(({ node }) => ( + {node.alt}/ +)) ``` Giving it an alias does not add a level of complexity to the response object, it just replaces it. So you end up with the same structure, referenced like this (note the alias `talks` in place of the longer `allSpeakingYaml`): ```jsx -{data.talks.edges.map(({ node }) => ()) +{data.talks.edges.map(({ node }) => ( + {node.alt}/ +)) ``` The top-level object name of `data` is implicit. This is important because when you conduct multiple queries as part of a single component, Gatsby still passes the entire result to the component. @@ -328,7 +326,9 @@ With that understanding, you can combine two queries referencing images and use Notice that this example uses aliasing for one query and not the other. This is allowed; there is no requirement that all your queries use aliasing. In this case, the JSX would look like this to access the `speaking.yaml` content. ```jsx -{data.allSpeakingYaml.edges.map(({ node }) => ()) +{data.allSpeakingYaml.edges.map(({ node }) => ( + {node.alt}/ +)) ``` And then like this to access the image using the alias name `banner`. From 0cbc9706683e563cf452359097669476065f378f Mon Sep 17 00:00:00 2001 From: Marcy Sutton Date: Mon, 15 Jul 2019 11:29:47 -0700 Subject: [PATCH 10/11] fix image-tutorial URL, add to sidebar --- .../{gatsby-image-tutorial.md => index.md} | 0 www/src/data/sidebars/tutorial-links.yaml | 2 ++ 2 files changed, 2 insertions(+) rename docs/tutorial/gatsby-image-tutorial/{gatsby-image-tutorial.md => index.md} (100%) diff --git a/docs/tutorial/gatsby-image-tutorial/gatsby-image-tutorial.md b/docs/tutorial/gatsby-image-tutorial/index.md similarity index 100% rename from docs/tutorial/gatsby-image-tutorial/gatsby-image-tutorial.md rename to docs/tutorial/gatsby-image-tutorial/index.md diff --git a/www/src/data/sidebars/tutorial-links.yaml b/www/src/data/sidebars/tutorial-links.yaml index b1959c319c614..64b446b3217e4 100644 --- a/www/src/data/sidebars/tutorial-links.yaml +++ b/www/src/data/sidebars/tutorial-links.yaml @@ -119,6 +119,8 @@ - title: Additional Tutorials link: /tutorial/additional-tutorials/ items: + - title: Using Gatsby Image with Your Site + link: /tutorial/gatsby-image-tutorial/ - title: Making a Site with User Authentication link: /tutorial/authentication-tutorial/ - title: Making an e-commerce Gatsby Site with Stripe From 9a8a28f9d86bf0363ff8573150eff81d21ce6d64 Mon Sep 17 00:00:00 2001 From: Marcy Sutton Date: Mon, 15 Jul 2019 11:30:01 -0700 Subject: [PATCH 11/11] rename wordpress image tutorial, add redirects --- .../2018-05-31-open-sourcing-gatsby-workshops/index.md | 2 +- .../{image-tutorial.md => wordpress-image-tutorial.md} | 0 docs/tutorial/wordpress-source-plugin-tutorial.md | 2 +- www/gatsby-node.js | 7 ++++++- www/src/data/sidebars/tutorial-links.yaml | 2 +- 5 files changed, 9 insertions(+), 4 deletions(-) rename docs/tutorial/{image-tutorial.md => wordpress-image-tutorial.md} (100%) diff --git a/docs/blog/2018-05-31-open-sourcing-gatsby-workshops/index.md b/docs/blog/2018-05-31-open-sourcing-gatsby-workshops/index.md index 0a7faf7a3109b..98373c043480e 100644 --- a/docs/blog/2018-05-31-open-sourcing-gatsby-workshops/index.md +++ b/docs/blog/2018-05-31-open-sourcing-gatsby-workshops/index.md @@ -29,7 +29,7 @@ And that's just one page of notes (there were many more). The biggest takeaways People are interested in tutorials that go beyond the basic [Tutorial](/tutorial/), so we created three new tutorials: - [WordPress Source Plugin Tutorial](/tutorial/wordpress-source-plugin-tutorial/) -- [Adding Images to a WordPress Site](/tutorial/image-tutorial/) +- [Adding Images to a WordPress Site](/tutorial/wordpress-image-tutorial/) - [Creating a Source Plugin](/docs/creating-a-source-plugin/) ## Why you might want to host a workshop diff --git a/docs/tutorial/image-tutorial.md b/docs/tutorial/wordpress-image-tutorial.md similarity index 100% rename from docs/tutorial/image-tutorial.md rename to docs/tutorial/wordpress-image-tutorial.md diff --git a/docs/tutorial/wordpress-source-plugin-tutorial.md b/docs/tutorial/wordpress-source-plugin-tutorial.md index 08521849372dd..c315594d9440b 100644 --- a/docs/tutorial/wordpress-source-plugin-tutorial.md +++ b/docs/tutorial/wordpress-source-plugin-tutorial.md @@ -6,7 +6,7 @@ title: "WordPress Source Plugin Tutorial" ### What this tutorial covers: -In this tutorial, you will install the `gatsby-source-wordpress` plugin in order to pull blog and image data from a WordPress install into your Gatsby site and render that data. This [Gatsby + WordPress demo site](https://github.com/gatsbyjs/gatsby/tree/master/examples/using-wordpress) shows you the source code for an example site similar to what you’re going to be building in this tutorial, although it’s missing the cool images you’ll be adding in the next part of this tutorial, [Adding Images to a WordPress Site](/tutorial/image-tutorial/). :D +In this tutorial, you will install the `gatsby-source-wordpress` plugin in order to pull blog and image data from a WordPress install into your Gatsby site and render that data. This [Gatsby + WordPress demo site](https://github.com/gatsbyjs/gatsby/tree/master/examples/using-wordpress) shows you the source code for an example site similar to what you’re going to be building in this tutorial, although it’s missing the cool images you’ll be adding in the next part of this tutorial, [Adding Images to a WordPress Site](/tutorial/wordpress-image-tutorial/). :D #### But do you prefer GraphQL? diff --git a/www/gatsby-node.js b/www/gatsby-node.js index 4769cd6168e84..97403bd3e7ce7 100644 --- a/www/gatsby-node.js +++ b/www/gatsby-node.js @@ -282,7 +282,12 @@ exports.createPages = ({ graphql, actions, reporter }) => { }) createRedirect({ fromPath: `/docs/image-tutorial/`, - toPath: `/tutorial/image-tutorial/`, + toPath: `/tutorial/wordpress-image-tutorial/`, + isPermanent: true, + }) + createRedirect({ + fromPath: `/tutorial/image-tutorial/`, + toPath: `/tutorial/wordpress-image-tutorial/`, isPermanent: true, }) createRedirect({ diff --git a/www/src/data/sidebars/tutorial-links.yaml b/www/src/data/sidebars/tutorial-links.yaml index 64b446b3217e4..a02b64dad5719 100644 --- a/www/src/data/sidebars/tutorial-links.yaml +++ b/www/src/data/sidebars/tutorial-links.yaml @@ -128,7 +128,7 @@ - title: Using the WordPress Source Plugin link: /tutorial/wordpress-source-plugin-tutorial/ - title: Adding Images to a WordPress Site - link: /tutorial/image-tutorial/ + link: /tutorial/wordpress-image-tutorial/ - title: Using the Prismic with GraphQL Source Plugin link: /tutorial/prismic-source-graphql-tutorial - title: Writing Documentation with Docz