DEV: API extra markup to image wrapper (#25575)
This commit is contained in:
parent
53a198ad55
commit
10b33bc601
|
@ -2,6 +2,30 @@ import I18n from "discourse-i18n";
|
|||
|
||||
const SCALES = ["100", "75", "50"];
|
||||
|
||||
let apiExtraButton = [];
|
||||
let apiExtraButtonAllowList = [];
|
||||
|
||||
export function addImageWrapperButton(label, btnClass, icon = null) {
|
||||
const markup = [];
|
||||
markup.push(`<span class="${btnClass}">`);
|
||||
if (icon) {
|
||||
markup.push(`
|
||||
<svg class="fa d-icon d-icon-${icon} svg-icon svg-string" xmlns="http://www.w3.org/2000/svg">
|
||||
<use href="#${icon}"></use>
|
||||
</svg>
|
||||
`);
|
||||
}
|
||||
markup.push(label);
|
||||
markup.push("</span>");
|
||||
|
||||
apiExtraButton.push(markup.join(""));
|
||||
apiExtraButtonAllowList.push(`span.${btnClass}`);
|
||||
apiExtraButtonAllowList.push(
|
||||
`svg[class=fa d-icon d-icon-${icon} svg-icon svg-string]`
|
||||
);
|
||||
apiExtraButtonAllowList.push(`use[href=#${icon}]`);
|
||||
}
|
||||
|
||||
function isUpload(token) {
|
||||
return token.content.includes("upload://");
|
||||
}
|
||||
|
@ -157,6 +181,8 @@ function ruleWithImageControls(oldRule) {
|
|||
result += `</span>`;
|
||||
result += buildImageDeleteButton();
|
||||
|
||||
result += apiExtraButton.join("");
|
||||
|
||||
result += "</span></span>";
|
||||
|
||||
return result;
|
||||
|
@ -205,6 +231,8 @@ export function setup(helper) {
|
|||
"span.wrap-image-grid-button[data-image-count]",
|
||||
"svg[class=fa d-icon d-icon-th svg-icon svg-string]",
|
||||
"use[href=#th]",
|
||||
|
||||
...apiExtraButtonAllowList,
|
||||
]);
|
||||
|
||||
helper.registerPlugin((md) => {
|
||||
|
|
|
@ -101,6 +101,12 @@ export function addComposerUploadMarkdownResolver(resolver) {
|
|||
export function cleanUpComposerUploadMarkdownResolver() {
|
||||
uploadMarkdownResolvers = [];
|
||||
}
|
||||
|
||||
let apiImageWrapperBtnEvents = [];
|
||||
export function addApiImageWrapperButtonClickEvent(fn) {
|
||||
apiImageWrapperBtnEvents.push(fn);
|
||||
}
|
||||
|
||||
export default Component.extend(ComposerUploadUppy, {
|
||||
classNameBindings: ["showToolbar:toolbar-visible", ":wmd-controls"],
|
||||
|
||||
|
@ -773,6 +779,12 @@ export default Component.extend(ComposerUploadUppy, {
|
|||
preview.addEventListener("click", this._handleImageDeleteButtonClick);
|
||||
preview.addEventListener("keypress", this._handleAltTextInputKeypress);
|
||||
preview.addEventListener("click", this._handleImageGridButtonClick);
|
||||
|
||||
if (apiImageWrapperBtnEvents.length > 0) {
|
||||
apiImageWrapperBtnEvents.forEach((fn) => {
|
||||
preview.addEventListener("click", fn);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
@on("willDestroyElement")
|
||||
|
@ -802,6 +814,12 @@ export default Component.extend(ComposerUploadUppy, {
|
|||
preview?.removeEventListener("click", this._handleImageGridButtonClick);
|
||||
preview?.removeEventListener("click", this._handleAltTextCancelButtonClick);
|
||||
preview?.removeEventListener("keypress", this._handleAltTextInputKeypress);
|
||||
|
||||
if (apiImageWrapperBtnEvents.length > 0) {
|
||||
apiImageWrapperBtnEvents.forEach((fn) => {
|
||||
preview?.removeEventListener("click", fn);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
onExpandPopupMenuOptions(toolbarEvent) {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import $ from "jquery";
|
||||
import { h } from "virtual-dom";
|
||||
import {
|
||||
addApiImageWrapperButtonClickEvent,
|
||||
addComposerUploadHandler,
|
||||
addComposerUploadMarkdownResolver,
|
||||
addComposerUploadPreProcessor,
|
||||
|
@ -132,6 +133,7 @@ import {
|
|||
registerIconRenderer,
|
||||
replaceIcon,
|
||||
} from "discourse-common/lib/icon-library";
|
||||
import { addImageWrapperButton } from "discourse-markdown-it/features/image-controls";
|
||||
import { CUSTOM_USER_SEARCH_OPTIONS } from "select-kit/components/user-chooser";
|
||||
import { modifySelectKit } from "select-kit/mixins/plugin-api";
|
||||
|
||||
|
@ -140,7 +142,7 @@ import { modifySelectKit } from "select-kit/mixins/plugin-api";
|
|||
// docs/CHANGELOG-JAVASCRIPT-PLUGIN-API.md whenever you change the version
|
||||
// using the format described at https://keepachangelog.com/en/1.0.0/.
|
||||
|
||||
export const PLUGIN_API_VERSION = "1.24.0";
|
||||
export const PLUGIN_API_VERSION = "1.25.0";
|
||||
|
||||
// This helper prevents us from applying the same `modifyClass` over and over in test mode.
|
||||
function canModify(klass, type, resolverName, changes) {
|
||||
|
@ -2687,6 +2689,26 @@ class PluginApi {
|
|||
.lookup("service:admin-custom-user-fields")
|
||||
.addProperty(userFieldProperty);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a custom button to the composer preview's image wrapper
|
||||
*
|
||||
*
|
||||
* ```
|
||||
* api.addComposerImageWrapperButton(
|
||||
* "My Custom Button",
|
||||
* "custom-button-class"
|
||||
* "lock"
|
||||
* (event) => { console.log("Custom button clicked", event)
|
||||
* });
|
||||
*
|
||||
* ```
|
||||
*
|
||||
*/
|
||||
addComposerImageWrapperButton(label, btnClass, icon, fn) {
|
||||
addImageWrapperButton(label, btnClass, icon);
|
||||
addApiImageWrapperButtonClickEvent(fn);
|
||||
}
|
||||
}
|
||||
|
||||
// from http://stackoverflow.com/questions/6832596/how-to-compare-software-version-number-using-js-only-number
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { click, fillIn, triggerKeyEvent, visit } from "@ember/test-helpers";
|
||||
import { test } from "qunit";
|
||||
import { withPluginApi } from "discourse/lib/plugin-api";
|
||||
import {
|
||||
acceptance,
|
||||
count,
|
||||
|
@ -376,3 +377,53 @@ acceptance("Composer - Image Preview", function (needs) {
|
|||
);
|
||||
});
|
||||
});
|
||||
|
||||
acceptance("Composer - Image Preview - Plugin API", function (needs) {
|
||||
needs.user({});
|
||||
needs.settings({ allow_uncategorized_topics: true });
|
||||
needs.site({ can_tag_topics: true });
|
||||
needs.pretender((server, helper) => {
|
||||
server.post("/uploads/lookup-urls", () => {
|
||||
return helper.response([]);
|
||||
});
|
||||
});
|
||||
|
||||
needs.hooks.beforeEach(() => {
|
||||
withPluginApi("1.25.0", (api) => {
|
||||
api.addComposerImageWrapperButton(
|
||||
"My Custom Button",
|
||||
"custom-button-class",
|
||||
"lock",
|
||||
(event) => {
|
||||
if (event.target.classList.contains("custom-button-class")) {
|
||||
document.querySelector(".d-editor-input").value =
|
||||
"custom button change";
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
test("image wrapper includes extra API button and is functional", async function (assert) {
|
||||
await visit("/");
|
||||
await click("#create-topic");
|
||||
|
||||
await fillIn(
|
||||
".d-editor-input",
|
||||
"![image_example_0|666x500](upload://q4iRxcuSAzfnbUaCsbjMXcGrpaK.jpeg)"
|
||||
);
|
||||
|
||||
assert.ok(
|
||||
exists(".image-wrapper .custom-button-class"),
|
||||
"The custom button is added to the image preview wrapper"
|
||||
);
|
||||
|
||||
await click(".custom-button-class");
|
||||
|
||||
assert.strictEqual(
|
||||
query(".d-editor-input").value,
|
||||
"custom button change",
|
||||
"The custom button changes the editor input"
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -7,6 +7,10 @@ in this file.
|
|||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [1.25.0] - 2024-02-05
|
||||
|
||||
- Added `addComposerImageWrapperButton` which is used to add a custom button to the composer preview's image wrapper that appears on hover of an uploaded image.
|
||||
|
||||
## [1.24.0] - 2024-01-08
|
||||
|
||||
- Added `addAdminSidebarSectionLink` which is used to add a link to a specific admin sidebar section, as a replacement for the `admin-menu` plugin outlet. This only has an effect if the `admin_sidebar_enabled_groups` site setting is in use, which enables the new admin nav sidebar.
|
||||
|
|
Loading…
Reference in New Issue