Add a way to auto-convert images in the chat into the img HTML tag
This commit is contained in:
parent
18021a32e4
commit
2a55ff522e
2 changed files with 123 additions and 0 deletions
|
|
@ -19,6 +19,7 @@ import { HotbarSettingsMenu } from "./apps/HotbarSettingsMenu.mjs";
|
||||||
|
|
||||||
// Misc
|
// Misc
|
||||||
import { __ID__ } from "./consts.mjs";
|
import { __ID__ } from "./consts.mjs";
|
||||||
|
import { chatImageLinks } from "./settings/chatImageLinks.mjs";
|
||||||
|
|
||||||
const { deepFreeze } = foundry.utils;
|
const { deepFreeze } = foundry.utils;
|
||||||
const status = {};
|
const status = {};
|
||||||
|
|
@ -46,6 +47,7 @@ Hooks.on(`setup`, () => {
|
||||||
status.hotbarButtonGap = hotbarButtonGap();
|
status.hotbarButtonGap = hotbarButtonGap();
|
||||||
status.repositionHotbar = repositionHotbar();
|
status.repositionHotbar = repositionHotbar();
|
||||||
|
|
||||||
|
status.chatImageLinks = chatImageLinks();
|
||||||
status.chatSidebarBackground = chatSidebarBackground();
|
status.chatSidebarBackground = chatSidebarBackground();
|
||||||
status.startSidebarExpanded = startSidebarExpanded();
|
status.startSidebarExpanded = startSidebarExpanded();
|
||||||
status.startingSidebarTab = startingSidebarTab();
|
status.startingSidebarTab = startingSidebarTab();
|
||||||
|
|
|
||||||
121
module/settings/chatImageLinks.mjs
Normal file
121
module/settings/chatImageLinks.mjs
Normal file
|
|
@ -0,0 +1,121 @@
|
||||||
|
import { __ID__ } from "../consts.mjs";
|
||||||
|
import { Logger } from "../utils/Logger.mjs";
|
||||||
|
|
||||||
|
const { DialogV2 } = foundry.applications.api;
|
||||||
|
|
||||||
|
const key = `chatImageLinks`;
|
||||||
|
const IMAGE_TYPES = [
|
||||||
|
`png`,
|
||||||
|
`jpg`,
|
||||||
|
`jpeg`,
|
||||||
|
`webp`,
|
||||||
|
`svg`,
|
||||||
|
];
|
||||||
|
|
||||||
|
export function chatImageLinks() {
|
||||||
|
|
||||||
|
// #region Registration
|
||||||
|
Logger.log(`Registering setting: ${key}`);
|
||||||
|
game.settings.register(__ID__, key, {
|
||||||
|
name: `OFT.setting.${key}.name`,
|
||||||
|
hint: `OFT.setting.${key}.hint`,
|
||||||
|
scope: `user`,
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
config: true,
|
||||||
|
requiresReload: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
game.settings.register(__ID__, key + `-showPromptAgain`, {
|
||||||
|
scope: `user`,
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
config: false,
|
||||||
|
});
|
||||||
|
// #endregion Registration
|
||||||
|
|
||||||
|
// #region Implementation
|
||||||
|
if (game.settings.get(__ID__, key)) {
|
||||||
|
Logger.log(`setting:${key} | Adding text enricher`);
|
||||||
|
|
||||||
|
// MARK: Enricher
|
||||||
|
const pattern = new RegExp(
|
||||||
|
`(?<!=|")(image:\\/\\/.*\\.(?:${IMAGE_TYPES.join(`|`)}))`,
|
||||||
|
`gi`,
|
||||||
|
);
|
||||||
|
|
||||||
|
CONFIG.TextEditor.enrichers.push({
|
||||||
|
pattern,
|
||||||
|
replaceParent: true,
|
||||||
|
enricher: async (url) => {
|
||||||
|
Logger.debug(url);
|
||||||
|
url = url[0].replace(/^image:\/\//, ``);
|
||||||
|
const secure = `https://${url}`;
|
||||||
|
const insecure = `http://${url}`;
|
||||||
|
|
||||||
|
if (await isAcceptableImage(secure)) {
|
||||||
|
const img = document.createElement(`img`);
|
||||||
|
img.src = secure;
|
||||||
|
img.alt = secure;
|
||||||
|
return img;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (await isAcceptableImage(insecure)) {
|
||||||
|
const img = document.createElement(`img`);
|
||||||
|
img.src = insecure;
|
||||||
|
img.alt = insecure;
|
||||||
|
return img;
|
||||||
|
};
|
||||||
|
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// MARK: Chat Input
|
||||||
|
// Hooks.on(`chatMessage`, (chatLog, message, options) => {
|
||||||
|
// if (!game.settings.get(__ID__, key)) { return };
|
||||||
|
|
||||||
|
// const match = message.match(pattern);
|
||||||
|
// if (!match) { return };
|
||||||
|
|
||||||
|
// DialogV2.wait({
|
||||||
|
// rejectClose: false,
|
||||||
|
// content: game.i18n.localize(`OFT.dialogs.chatImageLinks.didYouKnowImageLink`),
|
||||||
|
// buttons: [
|
||||||
|
// { action: ``, label: `OFT.dialogs.chatImageLinks.convertAndDontShowAgain` },
|
||||||
|
// { action: ``, label: `OFT.dialogs.chatImageLinks.justConvert` },
|
||||||
|
// { action: ``, label: `OFT.dialogs.chatImageLinks.ignoreAndDontShowAgain` },
|
||||||
|
// { action: ``, label: `OFT.dialogs.chatImageLinks.disableEntirely` },
|
||||||
|
// ],
|
||||||
|
// })
|
||||||
|
// .then((selected) => {
|
||||||
|
// chatLog.processMessage(message, options);
|
||||||
|
// });
|
||||||
|
|
||||||
|
// return false;
|
||||||
|
// });
|
||||||
|
}
|
||||||
|
// #endregion Implementation
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// #region Helpers
|
||||||
|
async function isAcceptableImage(url) {
|
||||||
|
try {
|
||||||
|
const response = await fetch(url, { method: `HEAD` });
|
||||||
|
const contentType = response.headers.get(`Content-Type`);
|
||||||
|
Logger.debug(`Image data:`, { url, contentType });
|
||||||
|
let [ superType, subtype ] = contentType.split(`/`);
|
||||||
|
if (superType !== `image`) {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
if (subtype.includes(`+`)) {
|
||||||
|
subtype = subtype.split(`+`, 2).at(0);
|
||||||
|
};
|
||||||
|
return IMAGE_TYPES.includes(subtype);
|
||||||
|
} catch {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
// #endregion Helpers
|
||||||
Loading…
Add table
Add a link
Reference in a new issue