TryGhost / Ghost

Independent technology for modern publishing, memberships, subscriptions and newsletters.
https://ghost.org
MIT License
46.93k stars 10.21k forks source link

Ghost Image Output #128

Closed JohnONolan closed 10 years ago

JohnONolan commented 11 years ago

A hypothetical scenario for clarity: One particular post looks something like this (image dimensions are of original uploaded media). This is the content which the user has defined.

Separately, the theme defines the following criteria about how it would like to display the images on the front end.

When a theme is activated/installed, it runs a process (preferably in the background, in order of newest to oldest) to resize images to the sizes it needs.

If any images are too small (the original media size) they are left alone.

Consideration: How does this work with 3rd party image services? Do they simply mirror the local Ghost image directory?

Featured Images

What if the concept of a "featured image" is simply the first image that appears (completely optionally) in any post.

Turning the concept of the WordPress featured image on its head - rather than the user being forced to create an entity defined as a thumbnail, the theme checks for something which it can use as a featured image.

Ghost scans a post to see if an image is available to use as a featured image - when it finds one, it uses it. If no image exists in the post which meets the required dimensions - a featured image is not assigned.

Markdown

We are extending markdown to produce some new functionality with the Ghost editor. By typing the following syntax:

!image[alt text](source)

an image uploader is generated in the content preview pane. Once an image is uploaded via this upload form, the markdown is then populated with the appropriate data. Eg:

!image[bananas](http://localhost/ghost/content/images/bananas.jpg)

Consideration: Is changing the official markdown tag of ![alt](src) to !image[alt](src) worth it? The initial thinking was to differentiate between image/video/something. But it might make sense to keep the ![alt](src) syntax for any type of media which is then detected automatically.

Multiple Image Sizes

Ghost does not support dynamic image sizes within content, it also does not support images being floated around differently within text. An image is a block of media equivalent to a paragraph. The theme can style that image to fit within its design.

It would be good if themes could define different sizes of image, so that users could still display content differently.

For example, an image that fits the width of the screen ("full") image

or an image that fits the width of the content ("standard") image

Considerations:

ErisDS commented 11 years ago

Long term, I'd like to have alt again, but short-term I think our functionality might conflict with showdown's default. Definitely worth investigating.

I think that a potential extension to haunted markdown that would solve multiple problems, would be to have the syntax be alt{size: standard, other-attr: other-value}

If no attrs are specified then defaults are used.

This would allow us to support alignments / floating. I know that the above says we don't support this, but I foresee it being a much requested feature... I use this feature of WP a lot on my own blog because I tend to include small low-quality images, like logos etc. Of course we can start without, but the attribute format I am recommending gives us plenty of opportunity to add new features. We could augment links in a similar way.. again, much further in the future when we have the editor much more under our own belt.

JohnONolan commented 11 years ago

There are a couple of lines we need to be conscious of when we start bastardising Markdown, which is that these 3 all exist for different reasons:

We just need to be a bit careful that we don't accidentally invent tag soup 2.0.

ErisDS commented 11 years ago

With regards to featured images being the first image in the post, this seems like a sub-optimal solution to me:

ErisDS commented 11 years ago

And yep, very wary of tag-soup... but also of limitations... perhaps we have one default image size, and a featured image defined in some other way, and as soon as the user specifies any other property (size or whatever) we default to putting HTML in the markdown.

JohnONolan commented 11 years ago

Why is the preview no longer a true preview? I think you're confusing "featured image" with "post thumbnail". The equivalent of single.php would have no concept of a post thumbnail. The post thumbnail would be used as a piece of UI for themes - eg. http://travelllll.com/must-read/ - nothing more.

RE complication - we can't get around this. It is complicated. Our choice is to either give that complication to the user, and make them deal with it (like the WordPress implementation of post thumbnail) or deal with the complication on the back end, and make things simple for the user. I'm obviously rather in favour of the latter :)

ErisDS commented 11 years ago

If this is the first image in the post, then we still leave that image in the post? The assumption I made is that we would do something different with it in every view. I made that assumption because no matter what the answer to the above is, we still have to find and serve that image separately, which is technically, not challenging, but smelly IMO. And if we have the image separately, then themes may choose to do something with it on eq.single.php .. which would require that it didn't also appear in the post.

In summary.. I think this approach adds complexity, not just for us but also for the user. I think we could use a ui within the editor to mark one image as the featured one, which would leave it in the post, but also store it as the feature. If the user didn;t want to use one from the post, they could upload separately through some other UI

JohnONolan commented 11 years ago

See what you're saying - I would suggest though, that if the featured image is always the first image in the post (and it had a unique class) - then it would be reasonably easy for a theme author to pull that image out of the flow of the content using CSS or JS, right?

ErisDS commented 11 years ago

Not really? That seems like the way you would hack it if we didn't support featured images as a feature. If we support it, we should support it properly.. or else just provide what you just described as a plugin.

JohnONolan commented 11 years ago

But it is a hack if a theme author wants to style a post thumbnail in a special way on a single post view. That's not what post thumbnail is designed for. The fact that the content can be pulled out of the document flow and re-arranged on an aesthetic basis is exactly (to the letter) what CSS was designed for.

Don't think about it as a "featured image" which is "an image at the start of a post on the single view" - this is a singular use-case that isn't central to the point of this feature: which is to abstract an image out of the post content and associate it with the title independently from the rest of the content.

cgiffard commented 11 years ago

There's actually a good way to do this without breaking markdown. Media Fragment URIs lets you specify sub-components of a given media resource with its URL (such as time or track in a video, or clipping the resource to certain dimensions.) It's as verbose or as simple as you want it to be, and works with a plain old hash (#) on the URL which will not damage the request if somehow it falls through to the browser, or a user copies the markdown source to use somewhere else.

http://www.w3.org/TR/media-frags/

User agents that support it will ignore declarations they don't understand, meaning you could extend it and use a syntax similar to the following: (while still retaining support for other declarations in the same URI.)

![alt](/images/myimage.jpg#thumb)
![alt](/images/myimage.jpg#full)
![alt](/images/myimage.jpg#poster)

Just a quick thought. :)

cgiffard commented 11 years ago

Just realised you wouldn't even need to write JS to provide basic support for it. You could easily match on a CSS attribute selector:

img[src$="#thumb"] {
    float: left;
    clear: right;
    width: 200px;
    height: 200px;
}
matthojo commented 11 years ago

I really like what @cgiffard is proposing. Could potentially make imports a lot easier too.

ErisDS commented 11 years ago

First of all.. this sounds most excellent. I have never seen it so wanted to take some time to sit down and read the spec & do a bit of research before I responded. Not sure how we're meant to keep up with all these new bits and pieces these days.

So as I understand it, media fragments allow you to define a temporal or spacial dimension of a resource. So what time to go to on a video/audio resource or how to clip an image resource. The spacial dimension is almost exactly what we need - being able to specify: http://placekitten.com/500/500#xywh=160,120,120,140 and get a correctly clipped image, but at the moment although the temporal dimension has been implemented by some browsers, spatial hasn't been implemented by any.

But, your suggestion was to invent our own media fragment uri to specify the "class" or "type" of image we want... allowing us to effectively use fragments to specify a class on an image in markdown. Which is kinda genius, I like it :) We can use css or javascript to target the class and provide functionality.

However, having read the spec I wanted to flag up this:

For media fragment addressing, both approaches - URI query and URI fragment - are useful. The main difference between a URI query and a URI fragment is that a URI query produces a new resource, while a URI fragment provides a secondary resource that has a relationship to the primary resource. URI fragments are resolved from the primary resource without another retrieval action. This means that a user agent should be capable to resolve a URI fragment on a resource it has already received without having to fetch more data from the server.

Therefore, if various sized images are generated on the server side as per John's original description, then media fragments are not what we want because we need to request a different image, not just change the one we have.

If we want to use css / js on the client side to do image processing, we could use fragments. We could even implement the spacial dimension syntax so that if it gets implemented in the future we can just turn our implementation off. There is the css clip property which I think has widespread support.

If we want to resize images on the server and serve the correct one, then we probably want to use standard query strings.

![alt](/images/myimage.jpg?size=thumb)
![alt](/images/myimage.jpg?size=full)
![alt](/images/myimage.jpg?size=poster)

We can of course provide a combination of both

![alt](/images/myimage.jpg?size=thumb#xywh=0,0,50,50)

Where the client side can take a particular sized image and further specify a modification.

Or

![alt](/images/myimage.jpg?size=standard#border)

Where .border is a class that adds a border to the image

Or

![alt](/images/myimage.jpg?size=standard#right)

Where .right is a class that displays the image right-aligned.

I think this opens up a world of possibilities, and whatever we decide is the best implementation, I think using the URI to define additional image properties is definitely the right idea.

cgiffard commented 11 years ago

I see no reason why we couldn't parse the URI-fragment data on the server and return a query string version to the client, since native support is a little thin on the ground at the moment. ;)

(That said, if we have a media-query that defines the same resource be downloaded and presented in multiple ways, using the URI-fragments natively on the client would obviously be better since it wouldn't have to download the resource twice.)

I like the idea of supporting the spatial dimension, but think that a shorthand form might be more palatable to most content authors. Mapping non-standard URI fragment parameters to HTML classes soundseasy to do, won't break anything, and totally possible to manage entirely in the markdown parser/HTML compiler without having to write any functionality anywhere else in the app.


With that in mind, for the time being, to recap... I propose we just parse the URI fragment, ignore standard parameters, and map anything else to an HTML class. As far as I've been able to ascertain from the spec, the URI fragment parameters follow exactly the same rules as QueryString params, so we could use the battle-hardened node parser to parse them to a hash, saving ourselves some bother.

The theme author can use the class name to format and/or clip the images accordingly in their CSS.

Then at a later date we can implement both server-side and client side support for sizing an image based on the spatial dimension (whoo cross-application-tier code sharing!)

ErisDS commented 11 years ago

As far as I understand it will depend entirely on the use case. If the media-fragment is added client-side there will be no new request so the client will never know about it in order to be able to parse it and return a query-string version.

For example, during actual image uploads on the editor: once the upload is complete we get given an image source and we place that into the preview. I imagine there will then be a set of icons you can click to decide what size you want the image to display... this adds a media fragment, but will not cause the image to update unless we do some other thing to tell the server.

But to clarify, I'm not disagreeing with anything you've said above, I'm just highlighting what I think might be problems that we would encounter.

ErisDS commented 11 years ago

Another consideration here, is how to handle images that have been uploaded to Ghost, vs images which are linked via a URL.

cgiffard commented 11 years ago

@ErisDS well that would actually be a great use case for fragments that address styling, since you could use them regardless of whether the image was hotlinked or uploaded to Ghost directly.

ErisDS commented 11 years ago

Punting all of this to 0.4

iraycd commented 10 years ago

I love @cgiffard idea. But I guess it'll be hard by users. ![alt](src){size: standard, other-attr: other-value} which I think is confusing for users.

Instead, I think why can't user add something ![featured_image]: src like at the end of the document. Which gives the variable {{feature_image.sizei}} in the template. Where size = big | small | mini which can be the values set in the settings or in config.json file in the template if that will be implemented in the future.

Please correct me if I'm wrong.

ErisDS commented 10 years ago

No time for the UX work here.. gonna keep this as the main issue for image features and punt to 0.5.

MikeRatcliffe commented 10 years ago

I hate to point out the obvious here but I don't necessarily want the image I use as a featured image to appear in a post. I would only want to show it in the summary list of all posts.

Also, I use HTML instead of markdown.

edoardoo commented 10 years ago

Hi, I've seen that one of the 'scaring' sides about modify the markdown is on UX complexity. For what is worth, I would propose some suggestions.

About Markdown: I think that having a markdown like

    ![alt](/images/myimage.jpg?size=thumb)

is a great solutions, which offers a lot of possible developments, although it could drive to some side effects, especially in situations like

![alt](/images/myimage.jpg?size=standard#right)

( just think about how js libraries, as prettyPhoto, implemented permalinks ). So, IMO is good to think about it a little more before hearing the theme-developer community crying blood.

About the UX: I think having a parallelism between markdown/HTML and preview is absolutely great and a must-need. To solve alignment and other properties settings I've thought about an 'on picture' icon/gear which open an on hover menu on the preview picture with some options. (see the picturebelow) Once clicked the option, it will be reflected on the markdown.

settings menu settings menu open

About the featured image: It's a very useful feature and really needed by a lot of theme developers. In the picture below are my two cents about where it could be a nice place to set it. Clicking on the pencil will open a modal window (?) where you can drag the featured picture.

featured menu

Sorry for long post, and excuse me for the intrusion.

StevenLangbroek commented 10 years ago

Can someone give me a status update on this? Considering Ghost for a client and this is essential for their layout and integrating blog-posts into their main marketing site. (jQuery trickery doesn't work since we need to pull in posts over json).

ErisDS commented 10 years ago

@StevenLangbroek what in particular are you interested in?

StevenLangbroek commented 10 years ago

Oh sorry, should've been more clear. The "cover / featured image" functionality.

ErisDS commented 10 years ago

There is an undocumented hack/workaround for that, which does have a bit of an explanation here: http://dev.ghost.org/ghost-0-4-themes/#anotetoallthemedevelopers. Despite being a hack, it has a test against it so it won't disappear until it is deprecated in favour of #therealthing.

Here's the plan for how the feature will work in terms of ui: https://github.com/TryGhost/Ghost-UI/issues/36. Roadmap is in a bit of flux at the moment, but it I expect this will land in the next feature release after MU.

JohnONolan commented 10 years ago

Moved on so far from this already. Advanced image controls should still be a thing - but this issue is stagnant and isn't worth keeping around. Future work/discussion can start in a new issue once we circle back around to this sort of concept (which is likely to be significantly different to things proposed here)