mirror of
https://github.com/discourse/discourse.git
synced 2025-02-25 18:55:32 -06:00
FEATURE: Allow post/topic thumbnails to be prioritized via markdown (#12044)
Previously we would always take the first image in a post to use as the thumbnail. On media-heavy sites, users may want to manually select a specific image as the topic thumbnail. This commit allows this to be done via a `|thumbnail` attribute in markdown. For example, in this case, bbb would be chosen as the thumbnail: ```   ```
This commit is contained in:
parent
a6bb7e6d25
commit
830797a9c3
@ -190,6 +190,7 @@ export const DEFAULT_LIST = [
|
|||||||
"img[height]",
|
"img[height]",
|
||||||
"img[title]",
|
"img[title]",
|
||||||
"img[width]",
|
"img[width]",
|
||||||
|
"img[data-thumbnail]",
|
||||||
"ins",
|
"ins",
|
||||||
"kbd",
|
"kbd",
|
||||||
"li",
|
"li",
|
||||||
|
@ -177,7 +177,7 @@ function renderImageOrPlayableMedia(tokens, idx, options, env, slf) {
|
|||||||
const token = tokens[idx];
|
const token = tokens[idx];
|
||||||
const alt = slf.renderInlineAsText(token.children, options, env);
|
const alt = slf.renderInlineAsText(token.children, options, env);
|
||||||
const split = alt.split("|");
|
const split = alt.split("|");
|
||||||
const altSplit = [];
|
const altSplit = [split[0]];
|
||||||
|
|
||||||
// markdown-it supports returning HTML instead of continuing to render the current token
|
// markdown-it supports returning HTML instead of continuing to render the current token
|
||||||
// see https://github.com/markdown-it/markdown-it/blob/master/docs/architecture.md#renderer
|
// see https://github.com/markdown-it/markdown-it/blob/master/docs/architecture.md#renderer
|
||||||
@ -195,7 +195,7 @@ function renderImageOrPlayableMedia(tokens, idx, options, env, slf) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// parsing ![myimage|500x300]() or ![myimage|75%]() or ![myimage|500x300, 75%]
|
// parsing ![myimage|500x300]() or ![myimage|75%]() or ![myimage|500x300, 75%]
|
||||||
for (let i = 0, match, data; i < split.length; ++i) {
|
for (let i = 1, match, data; i < split.length; ++i) {
|
||||||
if ((match = split[i].match(IMG_SIZE_REGEX)) && match[1] && match[2]) {
|
if ((match = split[i].match(IMG_SIZE_REGEX)) && match[1] && match[2]) {
|
||||||
let width = match[1];
|
let width = match[1];
|
||||||
let height = match[2];
|
let height = match[2];
|
||||||
@ -238,6 +238,8 @@ function renderImageOrPlayableMedia(tokens, idx, options, env, slf) {
|
|||||||
}
|
}
|
||||||
} else if ((data = extractDataAttribute(split[i]))) {
|
} else if ((data = extractDataAttribute(split[i]))) {
|
||||||
token.attrs.push(data);
|
token.attrs.push(data);
|
||||||
|
} else if (split[i] === "thumbnail") {
|
||||||
|
token.attrs.push(["data-thumbnail", "true"]);
|
||||||
} else {
|
} else {
|
||||||
altSplit.push(split[i]);
|
altSplit.push(split[i]);
|
||||||
}
|
}
|
||||||
|
@ -483,14 +483,20 @@ class CookedPostProcessor
|
|||||||
|
|
||||||
def update_post_image
|
def update_post_image
|
||||||
upload = nil
|
upload = nil
|
||||||
eligible_image_fragments = extract_images_for_post
|
images = extract_images_for_post
|
||||||
|
|
||||||
# Loop through those fragments until we find one with an upload record
|
@post.each_upload_url(fragments: images.css("[data-thumbnail]")) do |src, path, sha1|
|
||||||
@post.each_upload_url(fragments: eligible_image_fragments) do |src, path, sha1|
|
|
||||||
upload = Upload.find_by(sha1: sha1)
|
upload = Upload.find_by(sha1: sha1)
|
||||||
break if upload
|
break if upload
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if upload.nil? # No specified thumbnail. Use any image:
|
||||||
|
@post.each_upload_url(fragments: images.css(":not([data-thumbnail])")) do |src, path, sha1|
|
||||||
|
upload = Upload.find_by(sha1: sha1)
|
||||||
|
break if upload
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
if upload.present?
|
if upload.present?
|
||||||
@post.update_column(:image_upload_id, upload.id) # post
|
@post.update_column(:image_upload_id, upload.id) # post
|
||||||
if @post.is_first_post? # topic
|
if @post.is_first_post? # topic
|
||||||
|
@ -772,6 +772,19 @@ describe CookedPostProcessor do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "prioritizes data-thumbnail images" do
|
||||||
|
upload1 = Fabricate(:image_upload, width: 1750, height: 2000)
|
||||||
|
upload2 = Fabricate(:image_upload, width: 1750, height: 2000)
|
||||||
|
post = Fabricate(:post, raw: <<~MD)
|
||||||
|

|
||||||
|

|
||||||
|
MD
|
||||||
|
|
||||||
|
CookedPostProcessor.new(post, disable_loading_image: true).post_process
|
||||||
|
|
||||||
|
expect(post.reload.image_upload_id).to eq(upload2.id)
|
||||||
|
end
|
||||||
|
|
||||||
context "post image" do
|
context "post image" do
|
||||||
let(:reply) { Fabricate(:post_with_uploaded_image, post_number: 2) }
|
let(:reply) { Fabricate(:post_with_uploaded_image, post_number: 2) }
|
||||||
let(:cpp) { CookedPostProcessor.new(reply) }
|
let(:cpp) { CookedPostProcessor.new(reply) }
|
||||||
|
Loading…
Reference in New Issue
Block a user