-
-
Notifications
You must be signed in to change notification settings - Fork 657
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Resolve assets in markdown content #106
Comments
As far as I know, this is currently not supported out of the box. Maybe you can solve this with a component that dynamically loads the image for you, something like this? |
Yeah I thought about a solution like that, but not really compliant with content management tools :/ |
Hi there, The main issue here is that @nuxt/content is independent of Webpack, meaning that if you change anything in We are thinking of a way to support |
I see it was removed from the todo list. Any update on the situation of this feature request? |
Bumping, would love an update seeing as it has been removed from the To do? |
Don't pay too much attention to the todo list, we use it internally to plan the next release. We have considered this issue and will be working on it soon. |
The tricky part is to not involve Webpack for it when using images since it would force a rebuild and loose te speed of content update. |
@atinux might overwriting the html img tag by a custom component with the same attributes work for this case? |
Indeed your solution was quite good actually, if you can open a PR so we can work on it it would be great :) |
@atinux Maybe I'm missing something but why wouldn't I want webpack involved doing it's thing? Wouldn't I want webpack to rerun if content involving a webpack asset gets updated? |
The idea behing content is that you can change your Markdown without rebuilding your entire Nuxt app, making it faster redeployment. Tracking assets is a bit more tricky in that case since Content does not depend of Webpack at all. |
I fiddled around with it today and think I understood the way in which it could be implemented. I would be really interested in your thoughts about the API design. ![image alt text](~/assets/localimage.jpg) <img src="~/assets/localimage.jpg" alt="image alt text>
I have a few doubts about using the default tags and attributes because in this case, we would've to check if the developer is trying to load a local asset or remote image. <img local-src="~/assets/localimage.jpg" alt="image alt text>
|
Yeah both should be supported, this will give more control since you can't do basic things like center an image with markdown |
Is it possible to store the images under the content directory itself instead of in the assets directory? Then you could create a structure like: content/articles/my-new-article/index.md which would keep all the content together. |
Yes but this should not be the only solution.. again to have more control pointing to a specific folder is useful in case someone wants to use a CDN/reverse proxy to serve the images. |
@davydnorris suggestion was helpful to me I created a global <template>
<img :src="imgSrc()" :alt="alt" />
</template>
<script>
export default {
props: {
src: {
type: String,
required: true
},
alt: {
type: String,
required: true
}
},
methods: {
imgSrc() {
try {
return require(`~/content${this.src}`)
} catch (error) {
return null
}
}
}
}
</script> Make sure to register this component globally. <image
v-if="blog.Featured_Image"
:src="blog.dir + '/images/' + blog.Featured_Image"
:alt="blog.Title"
>
</image> Inside Markdown: <image src="/blog/my-blog-slug/images/Scripts.png" alt="Scripts"></image> I hope this will be helpful to someone. 🙌 |
I did the same thing but I am getting warnings when I compile the files of the form:
I thought I could ignore the warning, however when I then try to run export or dev, the process hangs and never completes, and I see the above warning in the generated javascript instead of the actual content. I'm not a webpack/babel config file expert, but it looks like the error is from webpack when it goes looking for the image files. I assume you could write a rule to exclude the md files somehow? But then would that mess up the content generation? Any help would be greatly appreciated |
Unfortunately, this is the only solution worked for me. I have the same warnings. However, it doesn't affect the build process. |
OK so I have made progress... I couldn't work out why my images were being converted during the build but their paths weren't - then I realised that the images I happened to be using were IMG_xxxx.JPG and I had them in the code as IMG_xxxx.jpg. As soon as I made them exactly the same they all got picked up. Still trying to get the custom image component inside the .md to work - @MuhaddiMu did you register yours as a global? |
@davydnorris My Image component is registered globally. I have a working example, you can check that too by cloning https://github.com/MuhaddiMu/Portfolio |
Many thanks - I have now got it working 🥇 The components directive doesn't seem to do exactly what it says in the guide. I had set up a subdirectory specifically for blog components, called 'content', and had registered that in my nuxt config with:
but it didn't seem to work. I then moved the components into the top level and set It finally worked when I copied your example exactly and added a 'global' subdirectory with Thank you for all your assistance!! |
Besides images used in HTML and markdown, what about images referenced in frontmatter? I've had to add these to img: /images/journey-ux.jpg
alt: Rocket soaring through space |
This were actually the first ones I got to work. I used the same approach as above but could use a normal component in my _slug.vue and preview components:
in your case you've already included the image subdirectory so just adjust the template accordingly |
@davydnorris Regarding the // nuxt.config.js
// ...
build: {
extend(config, { isDev, isClient }) {
config.module.rules.push({
test: /\.md$/i,
loader: 'ignore-loader'
})
}
}
// ... |
Many thanks @lucien144 - that's exactly what I was hoping someone would know! Will try that tomorrow |
What about linking to assets that are not images? For example, linking to a local pdf file with |
Yes. Assets from Markdown written with fully qualified URL ~/images/ to be resolvable either from Vue pages/ or components/ components as equal to from a Markdown file. I'm assuming we could have the place where to store those as configurable. Either from static, or from content, or assets. So we avoid having more than one notation for the same resource and the resource resolver in its context (remark's toTHML, or WebPack, or vite) to pick which ever its running. |
I gave up for now, even after I gave in and tried moving some images to assets/static and couldn't get anything to work. It's hard to find relevant examples of nuxt-image use, and I don't even know for if it is supposed to handle this use case in the first place (creating thumbnails somewhere in the static build or dev process). Some replies earlier in this issue, someone posted a more custom image transform procedure, but that seems rather involved and I had hoped that's what nuxt-image could be used for. Another fallback would be to just generate thumbnails completely manually using a script, and put those in content as well. I had a look at your github/blog. Looks nice, but it's super slow to load indeed, with that many images. I've starred it, in the hope that you'll find a brilliant solution :) |
This was going to be my next move - try seeing if I can get it working out of /static or /assets and create a parallel folder structure there.
I saw the bit above, and I think that's probably over my head right now in terms of implementation. I agree this was exactly what I was hoping nuxt-image would do. I've also tried the Pivale image loader package, but that doesn't seem to be actively maintained and I couldn't get it to work or figure out why it wasn't. At this point, I'll probably just write some python to generate the smaller sizes since I can do that pretty easily, but I'd love to have it done dynamically instead of having to do it each time. Perhaps I can integrate that into the build process somehow...
Thanks! |
One of the ones above is my implementation and, for me, it was super simple, and it's working really well. I use it for my blog on my site https://www.olivegroveit.com.au/blog. All images for each blog entry are stored under the blog folder and the image component loads them. I've since enhanced the component and added sizing, justification and wrap props so that I can have images embedded in text that wraps around them |
Thanks - I have something similar to this comment and what you describe here with my v-img component here. While your site does look great (and I actually searched you to see if I could find your code), I couldn't tell if your solution addresses my problem. I want to reduce load time by serving smaller image files. I'm not concerned with the presentation or resizing images in the sense of how they appear - that's already handled. Adding props just resizes the display of the image on the client side and I need to reduce it on the server before its sent to the client. |
Yeah you're right - my approach uses a single image size but I do spend a bit of time to adjust them to something reasonable before I use them |
This raises a good point.... if I generate the thumbnail images some other way (either storing them in GH or having some script called on the server as part of the build process, which will make deployment... not fast), the next question would be how to provide those as a srcset. But most of the srcset packages I've seen also want to handle their own image creation. I suppose the easy way would be to change my v-img component so that it links to the full size but has the img prop point to a reduced size but still not thumbnail, and have my postcard point to the thumbnail size and just do strip manip on the slug+base image name to get there. |
Thanks - I appreciate your suggestions, but I'd like to avoid doing that if I can. One other question for you though.... it looks like you've figured how to set the og:image header to the correct deployed url for your image. I'm struggling with figuring out how to do that. Any advice? |
This is how I did it:
|
Thank you! That's been bugging me almost as much as the image loading. |
I just searched youtube for nuxt image and watched one by 'Coding with Ben'. There's a few other videos as well, and it does look like nuxt-image should do exactly the sort of resizing you (and I) want. Time for some more experimenting.. |
In the meantime, I banged out a python script, added a But I haven't rewritten the v-img component to use the new files yet. I'm now wondering if I can avoid having to keep the thumbnails locally in dev - somehow give require the generated thumbnail location in production, but just use the fullsize when in dev.... EDIT: I consider this just a temporary hack - I'd still very much like to do this in a real way using nuxt-image if possible. I just don't have the knowledge/time to deep dive. If someone else gets it to work and has code to share, I'd love to see it! |
So now I have, which brings me to webpack errors when I try to rewrite the I think I need to learn more about webpack's module search, but any advice? And an extra thank you for all the help you've provided already! |
If you have a look way back up the thread, there were some changes we had to make to get webpack to play nice with the images under the content - this may help you work it out. The other thing I found was that the image name and its extension were case sensitive, so that's something you may need to check too
|
Thanks! I've got this (or something very close to it in my nuxt.config.js. And I thought about the case sensitive bit - I'm only testing with a single post where everything's lower case. But I hadn't noticed that GH was hiding quite a few replies above in a fold - I think I have some more to go read about the rehype approach. And this comment was interesting - I've tried now fixing the suffix extension as a literal to see if that made webpack happy, but not yet.
Also, I think I may have been reading this thread when I first wrote the vimg component a while back - it's suspiciously similar to what you were doing earlier. If so, I can maybe find a way to eliminate the |
Ok. I think I've got it. Turns out the problem was with the dot in the name I chose for the sub folder (.imgs). If I changed that, everything works. Code in the SO question and pull request on my repo summarizing the final changes. Thanks again to everyone. And would still like to be using nuxt-image instead :) |
I just copy all images to the static directory at build time, and use relative paths for images in markdown, this way the content folder could even be a separate repo, and the images will still show in that gh repo. at the top of your nuxt.config.js const fs = require('fs')
const path = require('path')
const copyContentImages = (src, dest, ignore = []) => {
const exists = fs.existsSync(src)
const stats = exists && fs.statSync(src)
const isDirectory = exists && stats.isDirectory()
if (isDirectory) {
if (!fs.existsSync(dest) || !fs.statSync(src).isDirectory()) {
fs.mkdirSync(dest)
}
fs.readdirSync(src).forEach((childItemName) => {
copyContentImages(
path.join(src, childItemName),
path.join(dest, childItemName),
ignore
)
})
} else {
const ext = path.extname(src)
if (!ignore.includes(ext)) {
fs.copyFileSync(src, dest)
}
}
}
copyContentImages('content', 'static', ['.md'])
export default {
// the-rest-of-nuxt-config.........
} |
|
I tried something similar (I'd link it but after searching for 10 min I can't find it in my repo) where I wrote a python script that would, on deployment, essentially mirror the /content folder structure inside /static (moving only files fitting an image filename pattern, leaving md and other things alone). I found it ran too slowly - copying several gigs around caused my build process on Netlify to timeout. You might want to run a short test to make sure you won't have the same problem if you take this approach. |
I'm a bit lost in the long discussion here: what is the currently recommended workaround for Nuxt 3 + Content v2? |
|
VitePress can reference static assets in markdown files. |
After playing with this issue for a while I found a relatively clean solution for this issue. First of all, you need a helper composable to be able to resolve assets dynamically. const assets = import.meta.glob('~/assets/**/*', {
import: 'default',
eager: true,
});
export const useAsset = (src: string) => {
return assets[src]?.toString() || src;
}; Then you have to replace a default image component from <script setup lang="ts">
defineProps<{
src: string;
width?: string | number;
height?: string | number;
alt?: string;
}>();
</script>
<template>
<img v-bind="$props" :src="useAsset(src)" />
</template> Now you could use Nuxt assets as native Markdown images. This works well for me. ![Test Image](/assets/test.png) |
@sealedsins Nice solution. Can we modify it so that we can use images stored anywhere, e.g., even in the I tend to place my images inside the same folder as the blogspot md file. |
@ManasMadrecha I tried changing import glob from Probably that was caused by a non-typical structure of my project folder (I have |
As of Nuxt 3, you can use the Nuxt Content Assets module: You can save your images along with your markdown content, then at runtime, the module copies images to a build-time folder, replaces any matching relative paths with public ones, and serves the images using Nitro. At build time, images are copied to the final build output. It even supports relative paths in frontmatter so you can get funky with custom components, etc. Zero config, and no more workarounds! |
I would like to know if it's possible to have the webpack assets resolution inside of markdown content ? To display webpack handeled's images.
Reproduction link: https://codesandbox.io/s/dawn-snowflake-fv7l4?file=/content/post.md
![](~/assets/photo.jpg)
(or<img src="~/assets/photo.jpg">
in html) the same way I would have in a component templateI'm not interested in putting files in the static folder since there is no compression and no hash for cache-busting.
The text was updated successfully, but these errors were encountered: