mirror of
https://github.com/discourse/discourse.git
synced 2024-11-25 19:03:45 +08:00
DEV: Improvements to auto grid images (#29317)
This PR is a follow-up to ea1473e532
. When we initially added the experimental feature for automatically adding `[grid]` to images, we add the [grid] surrounding images after all the uploads have been completed.
This can lead to confusion when `[grid]` is delayed to be added in the composer, as users may try to add grid manually leading to breakage. This also leads to issues with Discourse AI's automatic image caption feature.
**In this PR**: we simply move the logic to be added when the images are uploaded and processing. This way, `[grid]` surrounding images is added immediately. We also apply a fix for an edge-case to prevent images from being wrapped in `[grid]` when they are already inside `[grid]` tags.
This commit is contained in:
parent
28c5fb94d3
commit
cf44502cdf
|
@ -13,7 +13,6 @@ import {
|
||||||
displayErrorForBulkUpload,
|
displayErrorForBulkUpload,
|
||||||
displayErrorForUpload,
|
displayErrorForUpload,
|
||||||
getUploadMarkdown,
|
getUploadMarkdown,
|
||||||
IMAGE_MARKDOWN_REGEX,
|
|
||||||
isImage,
|
isImage,
|
||||||
validateUploadedFile,
|
validateUploadedFile,
|
||||||
} from "discourse/lib/uploads";
|
} from "discourse/lib/uploads";
|
||||||
|
@ -256,6 +255,10 @@ export default class UppyComposerUpload {
|
||||||
if (this.composerModel.privateMessage) {
|
if (this.composerModel.privateMessage) {
|
||||||
file.meta.for_private_message = true;
|
file.meta.for_private_message = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isImage(file.name)) {
|
||||||
|
this.#consecutiveImages.push(file.name);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -296,7 +299,6 @@ export default class UppyComposerUpload {
|
||||||
if (this.isDestroying || this.isDestroyed) {
|
if (this.isDestroying || this.isDestroyed) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const upload = this.#inProgressUploads.find(
|
const upload = this.#inProgressUploads.find(
|
||||||
(upl) => upl.id === file.id
|
(upl) => upl.id === file.id
|
||||||
);
|
);
|
||||||
|
@ -352,6 +354,14 @@ export default class UppyComposerUpload {
|
||||||
file.name
|
file.name
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const MIN_IMAGES_TO_AUTO_GRID = 3;
|
||||||
|
if (
|
||||||
|
this.siteSettings.experimental_auto_grid_images &&
|
||||||
|
this.#consecutiveImages?.length >= MIN_IMAGES_TO_AUTO_GRID
|
||||||
|
) {
|
||||||
|
this.#autoGridImages();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -367,11 +377,6 @@ export default class UppyComposerUpload {
|
||||||
getUploadMarkdown(upload)
|
getUploadMarkdown(upload)
|
||||||
);
|
);
|
||||||
|
|
||||||
// Track consecutive images for surrounding with [grid] later:
|
|
||||||
if (isImage(upload.url)) {
|
|
||||||
this.#consecutiveImages.push(markdown);
|
|
||||||
}
|
|
||||||
|
|
||||||
cacheShortUploadUrl(upload.short_url, upload);
|
cacheShortUploadUrl(upload.short_url, upload);
|
||||||
|
|
||||||
new ComposerVideoThumbnailUppy(getOwner(this)).generateVideoThumbnail(
|
new ComposerVideoThumbnailUppy(getOwner(this)).generateVideoThumbnail(
|
||||||
|
@ -398,13 +403,6 @@ export default class UppyComposerUpload {
|
||||||
`${this.composerEventPrefix}:all-uploads-complete`
|
`${this.composerEventPrefix}:all-uploads-complete`
|
||||||
);
|
);
|
||||||
|
|
||||||
const MIN_IMAGES_TO_AUTO_GRID = 3;
|
|
||||||
if (
|
|
||||||
this.siteSettings.experimental_auto_grid_images &&
|
|
||||||
this.#consecutiveImages?.length >= MIN_IMAGES_TO_AUTO_GRID
|
|
||||||
) {
|
|
||||||
this.#autoGridImages();
|
|
||||||
}
|
|
||||||
this.#displayBufferedErrors();
|
this.#displayBufferedErrors();
|
||||||
this.#reset();
|
this.#reset();
|
||||||
}
|
}
|
||||||
|
@ -735,20 +733,51 @@ export default class UppyComposerUpload {
|
||||||
#autoGridImages() {
|
#autoGridImages() {
|
||||||
const reply = this.composerModel.get("reply");
|
const reply = this.composerModel.get("reply");
|
||||||
const imagesToWrapGrid = new Set(this.#consecutiveImages);
|
const imagesToWrapGrid = new Set(this.#consecutiveImages);
|
||||||
const matches = reply.match(IMAGE_MARKDOWN_REGEX) || [];
|
|
||||||
|
|
||||||
|
const uploadingText = I18n.t("uploading_filename", {
|
||||||
|
filename: "%placeholder%",
|
||||||
|
});
|
||||||
|
const uploadingTextMatch = uploadingText.match(/^.*(?=: %placeholder%…)/);
|
||||||
|
|
||||||
|
if (!uploadingTextMatch || !uploadingTextMatch[0]) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uploadingImagePattern = new RegExp(
|
||||||
|
"\\[" + uploadingTextMatch[0].trim() + ": ([^\\]]+?)\\.\\w+…\\]\\(\\)",
|
||||||
|
"g"
|
||||||
|
);
|
||||||
|
|
||||||
|
const matches = reply.match(uploadingImagePattern) || [];
|
||||||
const foundImages = [];
|
const foundImages = [];
|
||||||
matches.forEach((fullImageMarkdown) => {
|
|
||||||
fullImageMarkdown = fullImageMarkdown.trim();
|
|
||||||
|
|
||||||
// Check if the matched image markdown is in the imagesToWrapGrid
|
const existingGridPattern = /\[grid\]([\s\S]*?)\[\/grid\]/g;
|
||||||
if (imagesToWrapGrid.has(fullImageMarkdown)) {
|
const gridMatches = reply.match(existingGridPattern);
|
||||||
foundImages.push(fullImageMarkdown);
|
|
||||||
imagesToWrapGrid.delete(fullImageMarkdown);
|
|
||||||
|
|
||||||
// Check if we've found all the images
|
matches.forEach((imagePlaceholder) => {
|
||||||
if (imagesToWrapGrid.size === 0) {
|
imagePlaceholder = imagePlaceholder.trim();
|
||||||
return;
|
|
||||||
|
const filenamePattern = new RegExp(
|
||||||
|
"\\[" + uploadingTextMatch[0].trim() + ": ([^\\]]+?)\\…\\]\\(\\)"
|
||||||
|
);
|
||||||
|
|
||||||
|
const filenameMatch = imagePlaceholder.match(filenamePattern);
|
||||||
|
|
||||||
|
if (filenameMatch && filenameMatch[1]) {
|
||||||
|
const filename = filenameMatch[1];
|
||||||
|
|
||||||
|
const isWithinGrid = gridMatches?.some((gridContent) =>
|
||||||
|
gridContent.includes(imagePlaceholder)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!isWithinGrid && imagesToWrapGrid.has(filename)) {
|
||||||
|
foundImages.push(imagePlaceholder);
|
||||||
|
imagesToWrapGrid.delete(filename);
|
||||||
|
|
||||||
|
// Check if we've found all the images
|
||||||
|
if (imagesToWrapGrid.size === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -778,6 +807,7 @@ export default class UppyComposerUpload {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear found images for the next consecutive images:
|
// Clear found images for the next consecutive images:
|
||||||
this.#consecutiveImages.length = 0;
|
this.#consecutiveImages.length = 0;
|
||||||
foundImages.length = 0;
|
foundImages.length = 0;
|
||||||
|
|
|
@ -244,5 +244,43 @@ describe "Uploading files in the composer", type: :system do
|
||||||
%r{!\[.*?\]\(upload://.*?\).*!\[.*?\]\(upload://.*?\).*!\[.*?\]\(upload://.*?\)}m,
|
%r{!\[.*?\]\(upload://.*?\).*!\[.*?\]\(upload://.*?\).*!\[.*?\]\(upload://.*?\)}m,
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "does not automatically wrap images in [grid] tags when uploading inside an existing [grid]" do
|
||||||
|
visit "/new-topic"
|
||||||
|
expect(composer).to be_opened
|
||||||
|
|
||||||
|
composer.fill_content("[grid]\n\n[/grid]")
|
||||||
|
composer.move_cursor_after("[grid]\n")
|
||||||
|
|
||||||
|
file_path_1 = file_from_fixtures("logo.png", "images").path
|
||||||
|
file_path_2 = file_from_fixtures("logo.jpg", "images").path
|
||||||
|
file_path_3 = file_from_fixtures("downsized.png", "images").path
|
||||||
|
attach_file([file_path_1, file_path_2, file_path_3]) do
|
||||||
|
composer.click_toolbar_button("upload")
|
||||||
|
end
|
||||||
|
expect(composer).to have_no_in_progress_uploads
|
||||||
|
expect(composer.composer_input.value).to match(
|
||||||
|
%r{\[grid\].*!\[.*?\]\(upload://.*?\).*!\[.*?\]\(upload://.*?\).*!\[.*?\]\(upload://.*?\).*?\[/grid\]}m,
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "automatically wraps images in [grid] when site language is different" do
|
||||||
|
SiteSetting.default_locale = "es"
|
||||||
|
|
||||||
|
visit "/new-topic"
|
||||||
|
expect(composer).to be_opened
|
||||||
|
|
||||||
|
file_path_1 = file_from_fixtures("logo.png", "images").path
|
||||||
|
file_path_2 = file_from_fixtures("logo.jpg", "images").path
|
||||||
|
file_path_3 = file_from_fixtures("downsized.png", "images").path
|
||||||
|
attach_file([file_path_1, file_path_2, file_path_3]) do
|
||||||
|
composer.click_toolbar_button("upload")
|
||||||
|
end
|
||||||
|
|
||||||
|
expect(composer).to have_no_in_progress_uploads
|
||||||
|
expect(composer.composer_input.value).to match(
|
||||||
|
%r{\[grid\].*!\[.*?\]\(upload://.*?\).*!\[.*?\]\(upload://.*?\).*!\[.*?\]\(upload://.*?\).*?\[/grid\]}m,
|
||||||
|
)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue
Block a user