const icon = ``; class ContextualAltController extends window.StimulusModule.Controller { static targets = ['suggest']; static values = { imageInput: { default: '', type: String }, captionInput: { default: '', type: String }, }; /** An image-to-text pipeline, shared between all instances of this controller. */ static captioner; static { this.captioner = import( 'https://cdn.jsdelivr.net/npm/@xenova/transformers@2.17.2' ).then(({ pipeline }) => pipeline('image-to-text', 'Mozilla/distilvit')); } get imageURL() { return this.element.querySelector('img[data-chooser-image]')?.src || ''; } /** @returns {HTMLElement} */ get element() { return super.element; } connect() { this.summarize = this.summarize.bind(this); this.renderFurniture(); } imageInputValueChanged() { if (this.imageInputValue) { this.imageInput = this.element.querySelector(this.imageInputValue); } else { this.imageInput = null; } if (this.hasSuggestTarget) this.toggleSuggestTarget(); } captionInputValueChanged() { if (this.captionInputValue) { this.captionInput = this.element.querySelector(this.captionInputValue); } else { this.captionInput = null; } } toggleSuggestTarget(event) { if (event?.target && event.target !== this.imageInput) return; this.suggestTarget.disabled = !this.imageInput?.value; } renderFurniture() { this.renderSuggestButton(); this.renderOutputArea(); this.toggleSuggestTarget(); } renderSuggestButton() { if (this.hasSuggestTarget) return; const prefix = this.element.closest('[id]').id; const buttonId = `${prefix}-generate`; const button = /* html */ ` `; this.element.insertAdjacentHTML('beforeend', button); } renderOutputArea() { const css = new CSSStyleSheet(); css.replaceSync(/* css */ ` .suggestion { display: block; margin-top: 0.5rem; margin-bottom: 0.5rem; border-radius: 0.25rem; padding: 0.5rem; background-color: lightblue; color: black; } `); this.outputArea = document.createElement('div'); document.adoptedStyleSheets.push(css); this.element.append(this.outputArea); } renderSuggestion(suggestion) { const template = document.createElement('template'); template.innerHTML = /* html */ `
${suggestion}
`; this.outputArea.append(template.content.firstElementChild); } useSuggestion(event) { if (!this.captionInput) return; console.log(event.target); this.captionInput.value = event.target.previousElementSibling.textContent; } async caption(imageURL) { const output = await (await ContextualAltController.captioner)(imageURL); return output[0].generated_text; } async summarize() { this.outputArea.innerHTML = ''; // Clear previous output this.suggestTarget.lastElementChild.textContent = 'Generating…'; this.suggestTarget.disabled = true; const url = this.imageURL; await Promise.allSettled( [...Array(3).keys()].map(() => this.caption(url).then((output) => { this.renderSuggestion(output); }), ), ); this.suggestTarget.disabled = false; this.suggestTarget.lastElementChild.textContent = 'Generate suggestions'; } disconnect() { ContextualAltController.captioner.then((captioner) => captioner.dispose()); } } window.wagtail.app.register('contextual-alt', ContextualAltController);