Merge branch 'MDL-78453-main' of https://github.com/meirzamoodle/moodle
This commit is contained in:
@@ -1,10 +1,10 @@
|
||||
define("tiny_aiplacement/mediaimage",["exports","core/str","tiny_media/image","core/notification","core/prefetch"],(function(_exports,_str,_image,_notification,_prefetch){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}
|
||||
define("tiny_aiplacement/mediaimage",["exports","core/str","tiny_media/image","core/notification","core/prefetch","tiny_media/imagehelpers"],(function(_exports,_str,_image,_notification,_prefetch,_imagehelpers){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}
|
||||
/**
|
||||
* AI Modal for Tiny.
|
||||
*
|
||||
* @module tiny_aiplacement/mediaimage
|
||||
* @copyright 2024 Matt Porritt <matt.porritt@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_image=_interopRequireDefault(_image),_notification=_interopRequireDefault(_notification),(0,_prefetch.prefetchStrings)("core_ai",["contentwatermark"]);class AiMediaImage extends _image.default{constructor(editor,url,alt){super(editor),this.generatedImageUrl=url,this.altText=alt,(0,_str.getString)("contentwatermark","core_ai").then((watermark=>{this.watermark=watermark})).catch(_notification.default.exception)}getSelectedImage(){const imgElement=document.createElement("img");return imgElement.src=this.generatedImageUrl,imgElement.alt=this.truncateAltText(this.altText),imgElement}truncateAltText(altText){const watermark=" - "+this.watermark;if(altText.length+watermark.length<=125)altText+=watermark;else{const remainingLength=125-watermark.length-"...".length;altText=altText.substring(0,remainingLength)+"..."+watermark}return altText}}return _exports.default=AiMediaImage,_exports.default}));
|
||||
*/Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_image=_interopRequireDefault(_image),_notification=_interopRequireDefault(_notification),(0,_prefetch.prefetchStrings)("core_ai",["contentwatermark"]);class AiMediaImage extends _image.default{constructor(editor,url,alt){super(editor),this.generatedImageUrl=url,this.altText=alt,(0,_str.getString)("contentwatermark","core_ai").then((watermark=>{this.watermark=watermark})).catch(_notification.default.exception)}getSelectedImage(){const imgElement=document.createElement("img");return imgElement.src=this.generatedImageUrl,imgElement.alt=this.truncateAltText(this.altText),imgElement}truncateAltText(altText){const maximumAltTextLength=_imagehelpers.MAX_LENGTH_ALT,watermark=" - "+this.watermark;if(altText.length+watermark.length<=maximumAltTextLength)altText+=watermark;else{const remainingLength=maximumAltTextLength-watermark.length-"...".length;altText=altText.substring(0,remainingLength)+"..."+watermark}return altText}}return _exports.default=AiMediaImage,_exports.default}));
|
||||
|
||||
//# sourceMappingURL=mediaimage.min.js.map
|
||||
@@ -1 +1 @@
|
||||
{"version":3,"file":"mediaimage.min.js","sources":["../src/mediaimage.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * AI Modal for Tiny.\n *\n * @module tiny_aiplacement/mediaimage\n * @copyright 2024 Matt Porritt <[email protected]>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport {getString} from 'core/str';\nimport MediaImage from 'tiny_media/image';\nimport Notification from 'core/notification';\nimport {prefetchStrings} from 'core/prefetch';\n\nprefetchStrings('core_ai', [\n 'contentwatermark',\n]);\n\nexport default class AiMediaImage extends MediaImage {\n constructor(editor, url, alt) {\n super(editor); // Call the parent class constructor\n this.generatedImageUrl = url;\n this.altText = alt;\n getString('contentwatermark', 'core_ai').then((watermark) => {\n this.watermark = watermark;\n return;\n }).catch(Notification.exception);\n }\n\n getSelectedImage() {\n const imgElement = document.createElement('img');\n\n // Set attributes for the img element\n imgElement.src = this.generatedImageUrl;\n imgElement.alt = this.truncateAltText(this.altText);\n\n return imgElement;\n }\n\n /**\n * Truncate the alt text if it is longer than the maximum length.\n * @param {String} altText The alt text\n * @return {string} The truncated alt text\n */\n truncateAltText(altText) {\n const maximumAltTextLength = 125;\n const watermark = ' - ' + this.watermark;\n const ellipsis = '...';\n\n // Append the watermark to the alt text.\n if (altText.length + watermark.length <= maximumAltTextLength) {\n altText = altText + watermark;\n } else {\n const remainingLength = maximumAltTextLength - watermark.length - ellipsis.length;\n altText = altText.substring(0, remainingLength) + ellipsis + watermark;\n }\n return altText;\n }\n}\n"],"names":["AiMediaImage","MediaImage","constructor","editor","url","alt","generatedImageUrl","altText","then","watermark","catch","Notification","exception","getSelectedImage","imgElement","document","createElement","src","this","truncateAltText","length","remainingLength","substring"],"mappings":";;;;;;;6MA4BgB,UAAW,CACvB,2BAGiBA,qBAAqBC,eACtCC,YAAYC,OAAQC,IAAKC,WACfF,aACDG,kBAAoBF,SACpBG,QAAUF,uBACL,mBAAoB,WAAWG,MAAMC,iBACtCA,UAAYA,aAElBC,MAAMC,sBAAaC,WAG1BC,yBACUC,WAAaC,SAASC,cAAc,cAG1CF,WAAWG,IAAMC,KAAKZ,kBACtBQ,WAAWT,IAAMa,KAAKC,gBAAgBD,KAAKX,SAEpCO,WAQXK,gBAAgBZ,eAENE,UAAY,MAAQS,KAAKT,aAI3BF,QAAQa,OAASX,UAAUW,QALF,IAMzBb,SAAoBE,cACjB,OACGY,gBARmB,IAQsBZ,UAAUW,OAN5C,MAM8DA,OAC3Eb,QAAUA,QAAQe,UAAU,EAAGD,iBAPlB,MAOgDZ,iBAE1DF"}
|
||||
{"version":3,"file":"mediaimage.min.js","sources":["../src/mediaimage.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * AI Modal for Tiny.\n *\n * @module tiny_aiplacement/mediaimage\n * @copyright 2024 Matt Porritt <[email protected]>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport {getString} from 'core/str';\nimport MediaImage from 'tiny_media/image';\nimport Notification from 'core/notification';\nimport {prefetchStrings} from 'core/prefetch';\nimport {MAX_LENGTH_ALT} from 'tiny_media/imagehelpers';\n\nprefetchStrings('core_ai', [\n 'contentwatermark',\n]);\n\nexport default class AiMediaImage extends MediaImage {\n constructor(editor, url, alt) {\n super(editor); // Call the parent class constructor\n this.generatedImageUrl = url;\n this.altText = alt;\n getString('contentwatermark', 'core_ai').then((watermark) => {\n this.watermark = watermark;\n return;\n }).catch(Notification.exception);\n }\n\n getSelectedImage() {\n const imgElement = document.createElement('img');\n\n // Set attributes for the img element\n imgElement.src = this.generatedImageUrl;\n imgElement.alt = this.truncateAltText(this.altText);\n\n return imgElement;\n }\n\n /**\n * Truncate the alt text if it is longer than the maximum length.\n * @param {String} altText The alt text\n * @return {string} The truncated alt text\n */\n truncateAltText(altText) {\n const maximumAltTextLength = MAX_LENGTH_ALT;\n const watermark = ' - ' + this.watermark;\n const ellipsis = '...';\n\n // Append the watermark to the alt text.\n if (altText.length + watermark.length <= maximumAltTextLength) {\n altText = altText + watermark;\n } else {\n const remainingLength = maximumAltTextLength - watermark.length - ellipsis.length;\n altText = altText.substring(0, remainingLength) + ellipsis + watermark;\n }\n return altText;\n }\n}\n"],"names":["AiMediaImage","MediaImage","constructor","editor","url","alt","generatedImageUrl","altText","then","watermark","catch","Notification","exception","getSelectedImage","imgElement","document","createElement","src","this","truncateAltText","maximumAltTextLength","MAX_LENGTH_ALT","length","remainingLength","substring"],"mappings":";;;;;;;6MA6BgB,UAAW,CACvB,2BAGiBA,qBAAqBC,eACtCC,YAAYC,OAAQC,IAAKC,WACfF,aACDG,kBAAoBF,SACpBG,QAAUF,uBACL,mBAAoB,WAAWG,MAAMC,iBACtCA,UAAYA,aAElBC,MAAMC,sBAAaC,WAG1BC,yBACUC,WAAaC,SAASC,cAAc,cAG1CF,WAAWG,IAAMC,KAAKZ,kBACtBQ,WAAWT,IAAMa,KAAKC,gBAAgBD,KAAKX,SAEpCO,WAQXK,gBAAgBZ,eACNa,qBAAuBC,6BACvBZ,UAAY,MAAQS,KAAKT,aAI3BF,QAAQe,OAASb,UAAUa,QAAUF,qBACrCb,SAAoBE,cACjB,OACGc,gBAAkBH,qBAAuBX,UAAUa,OAN5C,MAM8DA,OAC3Ef,QAAUA,QAAQiB,UAAU,EAAGD,iBAPlB,MAOgDd,iBAE1DF"}
|
||||
@@ -25,6 +25,7 @@ import {getString} from 'core/str';
|
||||
import MediaImage from 'tiny_media/image';
|
||||
import Notification from 'core/notification';
|
||||
import {prefetchStrings} from 'core/prefetch';
|
||||
import {MAX_LENGTH_ALT} from 'tiny_media/imagehelpers';
|
||||
|
||||
prefetchStrings('core_ai', [
|
||||
'contentwatermark',
|
||||
@@ -57,7 +58,7 @@ export default class AiMediaImage extends MediaImage {
|
||||
* @return {string} The truncated alt text
|
||||
*/
|
||||
truncateAltText(altText) {
|
||||
const maximumAltTextLength = 125;
|
||||
const maximumAltTextLength = MAX_LENGTH_ALT;
|
||||
const watermark = ' - ' + this.watermark;
|
||||
const ellipsis = '...';
|
||||
|
||||
|
||||
+1
-1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -5,6 +5,6 @@ define("tiny_media/imagehelpers",["exports","core/templates"],(function(_exports
|
||||
* @module tiny_media/imagehelpers
|
||||
* @copyright 2024 Meirza <meirza.arson@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.showElements=_exports.isPercentageValue=_exports.hideElements=_exports.footerImageInsert=_exports.footerImageDetails=_exports.bodyImageInsert=_exports.bodyImageDetails=void 0,_templates=(obj=_templates)&&obj.__esModule?obj:{default:obj};_exports.bodyImageInsert=async(templateContext,root)=>_templates.default.renderForPromise("tiny_media/insert_image_modal_insert",{...templateContext}).then((_ref=>{let{html:html,js:js}=_ref;_templates.default.replaceNodeContents(root.querySelector(".tiny_image_body_template"),html,js)})).catch((error=>{window.console.log(error)}));_exports.footerImageInsert=async(templateContext,root)=>_templates.default.renderForPromise("tiny_media/insert_image_modal_insert_footer",{...templateContext}).then((_ref2=>{let{html:html,js:js}=_ref2;_templates.default.replaceNodeContents(root.querySelector(".tiny_image_footer_template"),html,js)})).catch((error=>{window.console.log(error)}));_exports.bodyImageDetails=async(templateContext,root)=>_templates.default.renderForPromise("tiny_media/insert_image_modal_details",{...templateContext}).then((_ref3=>{let{html:html,js:js}=_ref3;_templates.default.replaceNodeContents(root.querySelector(".tiny_image_body_template"),html,js)})).catch((error=>{window.console.log(error)}));_exports.footerImageDetails=async(templateContext,root)=>_templates.default.renderForPromise("tiny_media/insert_image_modal_details_footer",{...templateContext}).then((_ref4=>{let{html:html,js:js}=_ref4;_templates.default.replaceNodeContents(root.querySelector(".tiny_image_footer_template"),html,js)})).catch((error=>{window.console.log(error)}));_exports.showElements=(elements,root)=>{if(elements instanceof Array)elements.forEach((elementSelector=>{const element=root.querySelector(elementSelector);element&&element.classList.remove("d-none")}));else{const element=root.querySelector(elements);element&&element.classList.remove("d-none")}};_exports.hideElements=(elements,root)=>{if(elements instanceof Array)elements.forEach((elementSelector=>{const element=root.querySelector(elementSelector);element&&element.classList.add("d-none")}));else{const element=root.querySelector(elements);element&&element.classList.add("d-none")}};_exports.isPercentageValue=value=>value.match(/\d+%/)}));
|
||||
*/Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.showElements=_exports.isPercentageValue=_exports.hideElements=_exports.footerImageInsert=_exports.footerImageDetails=_exports.bodyImageInsert=_exports.bodyImageDetails=_exports.MAX_LENGTH_ALT=void 0,_templates=(obj=_templates)&&obj.__esModule?obj:{default:obj};_exports.MAX_LENGTH_ALT=750;_exports.bodyImageInsert=async(templateContext,root)=>_templates.default.renderForPromise("tiny_media/insert_image_modal_insert",{...templateContext}).then((_ref=>{let{html:html,js:js}=_ref;_templates.default.replaceNodeContents(root.querySelector(".tiny_image_body_template"),html,js)})).catch((error=>{window.console.log(error)}));_exports.footerImageInsert=async(templateContext,root)=>_templates.default.renderForPromise("tiny_media/insert_image_modal_insert_footer",{...templateContext}).then((_ref2=>{let{html:html,js:js}=_ref2;_templates.default.replaceNodeContents(root.querySelector(".tiny_image_footer_template"),html,js)})).catch((error=>{window.console.log(error)}));_exports.bodyImageDetails=async(templateContext,root)=>_templates.default.renderForPromise("tiny_media/insert_image_modal_details",{...templateContext}).then((_ref3=>{let{html:html,js:js}=_ref3;_templates.default.replaceNodeContents(root.querySelector(".tiny_image_body_template"),html,js)})).catch((error=>{window.console.log(error)}));_exports.footerImageDetails=async(templateContext,root)=>_templates.default.renderForPromise("tiny_media/insert_image_modal_details_footer",{...templateContext}).then((_ref4=>{let{html:html,js:js}=_ref4;_templates.default.replaceNodeContents(root.querySelector(".tiny_image_footer_template"),html,js)})).catch((error=>{window.console.log(error)}));_exports.showElements=(elements,root)=>{if(elements instanceof Array)elements.forEach((elementSelector=>{const element=root.querySelector(elementSelector);element&&element.classList.remove("d-none")}));else{const element=root.querySelector(elements);element&&element.classList.remove("d-none")}};_exports.hideElements=(elements,root)=>{if(elements instanceof Array)elements.forEach((elementSelector=>{const element=root.querySelector(elementSelector);element&&element.classList.add("d-none")}));else{const element=root.querySelector(elements);element&&element.classList.add("d-none")}};_exports.isPercentageValue=value=>value.match(/\d+%/)}));
|
||||
|
||||
//# sourceMappingURL=imagehelpers.min.js.map
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -37,6 +37,7 @@ import {
|
||||
showElements,
|
||||
hideElements,
|
||||
isPercentageValue,
|
||||
MAX_LENGTH_ALT,
|
||||
} from 'tiny_media/imagehelpers';
|
||||
|
||||
prefetchStrings('tiny_media', [
|
||||
@@ -155,7 +156,7 @@ export default class MediaImage {
|
||||
const currentImageData = await this.getCurrentImageData();
|
||||
let templateContext = await this.getTemplateContext(currentImageData);
|
||||
templateContext.sizecustomhelpicon = {text: await getString('sizecustom_help', 'tiny_media')};
|
||||
|
||||
templateContext.maxlengthalt = MAX_LENGTH_ALT;
|
||||
Promise.all([bodyImageDetails(templateContext, this.root), footerImageDetails(templateContext, this.root)])
|
||||
.then(() => {
|
||||
this.stopImageLoading();
|
||||
|
||||
@@ -23,6 +23,11 @@
|
||||
|
||||
import Templates from 'core/templates';
|
||||
|
||||
/**
|
||||
* Maximum length allowed for the alt attribute.
|
||||
*/
|
||||
export const MAX_LENGTH_ALT = 750;
|
||||
|
||||
/**
|
||||
* Renders and inserts the body template for inserting an image into the modal.
|
||||
*
|
||||
|
||||
@@ -34,6 +34,7 @@ import {
|
||||
hideElements,
|
||||
bodyImageDetails,
|
||||
footerImageDetails,
|
||||
MAX_LENGTH_ALT,
|
||||
} from 'tiny_media/imagehelpers';
|
||||
|
||||
prefetchStrings('tiny_media', [
|
||||
@@ -151,6 +152,7 @@ export class ImageInsert {
|
||||
image.addEventListener('load', () => {
|
||||
let templateContext = {};
|
||||
templateContext.sizecustomhelpicon = {text: this.langStrings.sizecustom_help};
|
||||
templateContext.maxlengthalt = MAX_LENGTH_ALT;
|
||||
Promise.all([bodyImageDetails(templateContext, this.root), footerImageDetails(templateContext, this.root)])
|
||||
.then(() => {
|
||||
const imagedetails = new ImageDetails(
|
||||
|
||||
@@ -29,7 +29,8 @@
|
||||
"customStyle": "",
|
||||
"sizecustomhelpicon": {
|
||||
"text": "Help text"
|
||||
}
|
||||
},
|
||||
"maxlengthalt": 750
|
||||
}
|
||||
|
||||
}}
|
||||
@@ -51,11 +52,12 @@
|
||||
<!-- Row 2: Image description -->
|
||||
<div class="form-group mt-3">
|
||||
<label for="{{elementid}}_tiny_image_altentry">{{#str}} enteralt, tiny_media {{/str}}</label>
|
||||
<textarea class="tiny_image_altentry form-control fullwidth" id="{{elementid}}_tiny_image_altentry" name="altentry" maxlength="125">{{alt}}</textarea>
|
||||
<textarea class="tiny_image_altentry form-control fullwidth" id="{{elementid}}_tiny_image_altentry" name="altentry" maxlength="{{maxlengthalt}}">{{alt}}</textarea>
|
||||
<!-- Character counter -->
|
||||
<div id="the-count" class="d-flex justify-content-end small">
|
||||
<span id="currentcount">0</span>
|
||||
<span id="maximumcount"> / 125</span>
|
||||
<span class="mx-1">/</span>
|
||||
<span id="maximumcount">{{maxlengthalt}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -64,3 +64,15 @@ Feature: Use the TinyMCE editor to upload an image
|
||||
Then the field "Custom size" matches value "1"
|
||||
And the field "Width" matches value "102"
|
||||
And the field "Keep proportion" matches value "0"
|
||||
|
||||
@_file_upload
|
||||
Scenario: Set the alt text to the maximum and below the maximum length
|
||||
Given I log in as "admin"
|
||||
And I open my profile in edit mode
|
||||
And I click on the "Image" button for the "Description" TinyMCE editor
|
||||
And I click on "Browse repositories" "button" in the "Insert image" "dialogue"
|
||||
And I upload "/lib/editor/tiny/tests/behat/fixtures/tinyscreenshot.png" to the file picker for TinyMCE
|
||||
When I set the field "How would you describe this image to someone who can't see it?" to "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu, consequat vitae, eleifend ac, enim. Aliquam lorem ante, dapibus in, viverra quis, feugiat a, tellus. Phasellus viverra nulla ut metus varius laoreet."
|
||||
Then I should see "750" in the "#currentcount" "css_element"
|
||||
And I set the field "How would you describe this image to someone who can't see it?" to "Lorem ipsum dolor sit amet."
|
||||
And I should see "27" in the "#currentcount" "css_element"
|
||||
|
||||
Reference in New Issue
Block a user