diff --git a/.eslintrc.json b/.eslintrc.json
index efa6c4ae0..ff6250aef 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -1,10 +1,13 @@
{
"env": {
"browser": true,
- "es6": true,
+ "es2024": true,
"jquery": true,
"greasemonkey": true
},
+ "parserOptions": {
+ "sourceType": "module"
+ },
"extends": [
"eslint:recommended",
"plugin:prettier/recommended",
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
new file mode 100644
index 000000000..65ecc852c
--- /dev/null
+++ b/.github/workflows/test.yml
@@ -0,0 +1,29 @@
+name: Tests
+'on':
+ push:
+ pull_request:
+ types:
+ - opened
+ - synchronize
+ - reopened
+
+jobs:
+ test:
+ name: 'Node.js v18'
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ - uses: actions/setup-node@v1
+ with:
+ node-version: '18'
+ - name: 'Cache node_modules'
+ uses: actions/cache@v2
+ with:
+ path: ~/.npm
+ key: ${{ runner.os }}-node-18-${{ hashFiles('**/package.json') }}
+ restore-keys: |
+ ${{ runner.os }}-node-18-
+ - name: Install Dependencies
+ run: npm install
+ - name: Run All Node.js Tests
+ run: npm run test
diff --git a/core/code/chat.js b/core/code/chat.js
index 822bafe13..99e2855cb 100644
--- a/core/code/chat.js
+++ b/core/code/chat.js
@@ -1,11 +1,83 @@
/**
* @file Namespace for chat-related functionalities.
*
- * @namespace chat
+ * @module chat
*/
var chat = function () {};
window.chat = chat;
+// List of functions to track for synchronization between chat and comm
+const legacyFunctions = [
+ 'genPostData',
+ 'updateOldNewHash',
+ 'parseMsgData',
+ 'writeDataToHash',
+ 'renderText',
+ 'getChatPortalName',
+ 'renderPortal',
+ 'renderFactionEnt',
+ 'renderPlayer',
+ 'renderMarkupEntity',
+ 'renderMarkup',
+ 'renderTimeCell',
+ 'renderNickCell',
+ 'renderMsgCell',
+ 'renderMsgRow',
+ 'renderDivider',
+ 'renderData',
+];
+const newCommApi = [
+ '_genPostData',
+ '_updateOldNewHash',
+ 'parseMsgData',
+ '_writeDataToHash',
+ 'renderText',
+ 'getChatPortalName',
+ 'renderPortal',
+ 'renderFactionEnt',
+ 'renderPlayer',
+ 'renderMarkupEntity',
+ 'renderMarkup',
+ 'renderTimeCell',
+ 'renderNickCell',
+ 'renderMsgCell',
+ 'renderMsgRow',
+ 'renderDivider',
+ 'renderData',
+];
+
+// Function to map legacy function names to their new names in comm
+function mapLegacyFunctionNameToCommApi(functionName) {
+ const index = legacyFunctions.indexOf(functionName);
+ return index !== -1 ? newCommApi[index] : functionName;
+}
+
+// Create a proxy for chat to ensure backward compatibility of migrated functions from chat to comm
+window.chat = new Proxy(window.chat, {
+ get(target, prop, receiver) {
+ if (prop in target) {
+ // Return the property from chat if it's defined
+ return target[prop];
+ } else if (legacyFunctions.includes(prop)) {
+ // Map the legacy function name to its new name in comm and return the corresponding function
+ const commProp = mapLegacyFunctionNameToCommApi(prop);
+ return window.IITC.comm[commProp];
+ }
+ // Return default value if the property is not found
+ return Reflect.get(target, prop, receiver);
+ },
+ set(target, prop, value) {
+ if (legacyFunctions.includes(prop)) {
+ // Map the legacy function name to its new name in comm and synchronize the function between chat and comm
+ const commProp = mapLegacyFunctionNameToCommApi(prop);
+ window.IITC.comm[commProp] = value;
+ }
+ // Update or add the property in chat
+ target[prop] = value;
+ return true; // Indicates that the assignment was successful
+ },
+});
+
//
// common
//
@@ -13,7 +85,7 @@ window.chat = chat;
/**
* Adds a nickname to the chat input.
*
- * @function chat.addNickname
+ * @function addNickname
* @param {string} nick - The nickname to add.
*/
chat.addNickname = function (nick) {
@@ -25,7 +97,7 @@ chat.addNickname = function (nick) {
/**
* Handles click events on nicknames in the chat.
*
- * @function chat.nicknameClicked
+ * @function nicknameClicked
* @param {Event} event - The click event.
* @param {string} nickname - The clicked nickname.
* @returns {boolean} Always returns false.
@@ -59,31 +131,31 @@ chat.nicknameClicked = function (event, nickname) {
* Hold channel description
*
* See comm.js for examples
- * @typedef {Object} chat.ChannelDescription
+ * @typedef {Object} ChannelDescription
* @property {string} id - uniq id, matches 'tab' parameter for server requests
* @property {string} name - visible name
* @property {string} [inputPrompt] - (optional) string for the input prompt
* @property {string} [inputClass] - (optional) class to apply to #chatinput
- * @property {chat.ChannelSendMessageFn} [sendMessage] - (optional) function to send the message
- * @property {chat.ChannelRequestFn} [request] - (optional) function to call to request new message
- * @property {chat.ChannelRenderFn} [render] - (optional) function to render channel content,, called on tab change
+ * @property {ChannelSendMessageFn} [sendMessage] - (optional) function to send the message
+ * @property {ChannelRequestFn} [request] - (optional) function to call to request new message
+ * @property {ChannelRenderFn} [render] - (optional) function to render channel content,, called on tab change
* @property {boolean} [localBounds] - (optional) if true, reset on view change
*/
/**
- * @callback chat.ChannelSendMessageFn
+ * @callback ChannelSendMessageFn
* @param {string} id - channel id
* @param {string} message - input message
* @returns {void}
*/
/**
- * @callback chat.ChannelRequestFn
+ * @callback ChannelRequestFn
* @param {string} id - channel id
* @param {boolean} getOlderMsgs - true if request data from a scroll to top
* @param {boolean} isRetry
* @returns {void}
*/
/**
- * @callback chat.ChannelRenderFn
+ * @callback ChannelRenderFn
* @param {string} id - channel id
* @param {boolean} oldMsgsWereAdded - true if data has been added at the top (to preserve scroll position)
* @returns {void}
@@ -92,14 +164,15 @@ chat.nicknameClicked = function (event, nickname) {
/**
* Holds channels infos.
*
- * @type {chat.ChannelDescription[]}
+ * @type {ChannelDescription[]}
+ * @memberof module:chat
*/
chat.channels = [];
/**
* Gets the name of the active chat tab.
*
- * @function chat.getActive
+ * @function getActive
* @returns {string} The name of the active chat tab.
*/
chat.getActive = function () {
@@ -109,9 +182,9 @@ chat.getActive = function () {
/**
* Converts a chat tab name to its corresponding channel object.
*
- * @function chat.getChannelDesc
+ * @function getChannelDesc
* @param {string} tab - The name of the chat tab.
- * @returns {chat.ChannelDescription} The corresponding channel name ('faction', 'alerts', or 'all').
+ * @returns {ChannelDescription} The corresponding channel name ('faction', 'alerts', or 'all').
*/
chat.getChannelDesc = function (tab) {
var channelObject = null;
@@ -126,7 +199,7 @@ chat.getChannelDesc = function (tab) {
* that need to process COMM data even when the user is not actively viewing the COMM channels.
* It tracks the requested channels for each plugin instance and updates the global state accordingly.
*
- * @function chat.backgroundChannelData
+ * @function backgroundChannelData
* @param {string} instance - A unique identifier for the plugin or instance requesting background COMM data.
* @param {string} channel - The name of the COMM channel ('all', 'faction', or 'alerts').
* @param {boolean} flag - Set to true to request data for the specified channel, false to stop requesting.
@@ -154,7 +227,7 @@ chat.backgroundChannelData = function (instance, channel, flag) {
* Requests chat messages for the currently active chat tab and background channels.
* It calls the appropriate request function based on the active tab or background channels.
*
- * @function chat.request
+ * @function request
*/
chat.request = function () {
var channel = chat.getActive();
@@ -169,7 +242,7 @@ chat.request = function () {
* Checks if the currently selected chat tab needs more messages.
* This function is triggered by scroll events and loads older messages when the user scrolls to the top.
*
- * @function chat.needMoreMessages
+ * @function needMoreMessages
*/
chat.needMoreMessages = function () {
var activeTab = chat.getActive();
@@ -190,7 +263,7 @@ chat.needMoreMessages = function () {
* Chooses and activates a specified chat tab.
* Also triggers an early refresh of the chat data when switching tabs.
*
- * @function chat.chooseTab
+ * @function chooseTab
* @param {string} tab - The name of the chat tab to activate ('all', 'faction', or 'alerts').
*/
chat.chooseTab = function (tab) {
@@ -246,7 +319,7 @@ chat.chooseTab = function (tab) {
* When expanded, the chat window covers a larger area of the screen.
* This function also ensures that the chat is scrolled to the bottom when collapsed.
*
- * @function chat.toggle
+ * @function toggle
*/
chat.toggle = function () {
var c = $('#chat, #chatcontrols');
@@ -266,7 +339,7 @@ chat.toggle = function () {
/**
* Displays the chat interface and activates a specified chat tab.
*
- * @function chat.show
+ * @function show
* @param {string} name - The name of the chat tab to show and activate.
*/
chat.show = function (name) {
@@ -285,7 +358,7 @@ chat.show = function (name) {
* This function is triggered by a click event on the chat tab. It reads the tab name from the event target
* and activates the corresponding chat tab.
*
- * @function chat.chooser
+ * @function chooser
* @param {Event} event - The event triggered by clicking a chat tab.
*/
chat.chooser = function (event) {
@@ -299,7 +372,7 @@ chat.chooser = function (event) {
* This function is designed to keep the scroll position fixed when old messages are loaded, and to automatically scroll
* to the bottom when new messages are added if the user is already at the bottom of the chat.
*
- * @function chat.keepScrollPosition
+ * @function keepScrollPosition
* @param {jQuery} box - The jQuery object of the chat box.
* @param {number} scrollBefore - The scroll position before new messages were added.
* @param {boolean} isOldMsgs - Indicates if the added messages are older messages.
@@ -327,7 +400,7 @@ chat.keepScrollPosition = function (box, scrollBefore, isOldMsgs) {
*
* @function createChannelTab
* @memberof chat
- * @param {chat.ChannelDescription} channelDesc - channel description
+ * @param {ChannelDescription} channelDesc - channel description
* @static
*/
function createChannelTab(channelDesc) {
@@ -362,8 +435,8 @@ var isTabsSetup = false;
*
* If tabs are already created, a tab is created for this channel as well
*
- * @function chat.addChannel
- * @param {chat.ChannelDescription} channelDesc - channel description
+ * @function addChannel
+ * @param {ChannelDescription} channelDesc - channel description
*/
chat.addChannel = function (channelDesc) {
// deny reserved name
@@ -391,8 +464,8 @@ chat.addChannel = function (channelDesc) {
/**
* Sets up all channels starting from intel COMM
*
- * @function chat.setupTabs
- * @param {chat.ChannelDescription} channelDesc - channel description
+ * @function setupTabs
+ * @param {ChannelDescription} channelDesc - channel description
*/
chat.setupTabs = function () {
isTabsSetup = true;
@@ -413,7 +486,7 @@ chat.setupTabs = function () {
/**
* Initiates a request for public chat data.
*
- * @function chat.requestPublic
+ * @function requestPublic
* @param {boolean} getOlderMsgs - Whether to retrieve older messages.
* @param {boolean} [isRetry=false] - Whether the request is a retry.
*/
@@ -424,7 +497,7 @@ chat.setupTabs = function () {
/**
* Requests faction chat messages.
*
- * @function chat.requestFaction
+ * @function requestFaction
* @param {boolean} getOlderMsgs - Flag to determine if older messages are being requested.
* @param {boolean} [isRetry=false] - Flag to indicate if this is a retry attempt.
*/
@@ -435,7 +508,7 @@ chat.setupTabs = function () {
/**
* Initiates a request for alerts chat data.
*
- * @function chat.requestAlerts
+ * @function requestAlerts
* @param {boolean} getOlderMsgs - Whether to retrieve older messages.
* @param {boolean} [isRetry=false] - Whether the request is a retry.
*/
@@ -446,7 +519,7 @@ chat.setupTabs = function () {
/**
* Renders public chat in the UI.
*
- * @function chat.renderPublic
+ * @function renderPublic
* @param {boolean} oldMsgsWereAdded - Indicates if older messages were added to the chat.
*/
chat.renderPublic = function (oldMsgsWereAdded) {
@@ -456,7 +529,7 @@ chat.setupTabs = function () {
/**
* Renders faction chat.
*
- * @function chat.renderFaction
+ * @function renderFaction
* @param {boolean} oldMsgsWereAdded - Indicates if old messages were added in the current rendering.
*/
chat.renderFaction = function (oldMsgsWereAdded) {
@@ -466,35 +539,18 @@ chat.setupTabs = function () {
/**
* Renders alerts chat in the UI.
*
- * @function chat.renderAlerts
+ * @function renderAlerts
* @param {boolean} oldMsgsWereAdded - Indicates if older messages were added to the chat.
*/
chat.renderAlerts = function (oldMsgsWereAdded) {
return IITC.comm.renderChannel('allerts', oldMsgsWereAdded);
};
-
- chat.getChatPortalName = IITC.comm.getChatPortalName;
-
- /**
- * Renders data from the data-hash to the element defined by the given ID.
- *
- * @function chat.renderData
- * @param {Object} data - Chat data to be rendered.
- * @param {string} element - ID of the DOM element to render the chat into.
- * @param {boolean} likelyWereOldMsgs - Flag indicating if older messages are likely to have been added.
- * @param {Array} sortedGuids - Sorted array of GUIDs representing the order of messages.
- * @memberof window.chat
- * @type {Object}
- */
- chat.renderData = function (data, element, likelyWereOldMsgs, sortedGuids) {
- return IITC.comm.renderData(data, element, likelyWereOldMsgs, sortedGuids);
- };
};
/**
* Sets up the chat interface.
*
- * @function chat.setup
+ * @function setup
*/
chat.setup = function () {
chat.setupTabs();
@@ -528,7 +584,7 @@ chat.setup = function () {
* Sets up the time display in the chat input box.
* This function updates the time displayed next to the chat input field every minute to reflect the current time.
*
- * @function chat.setupTime
+ * @function setupTime
*/
chat.setupTime = function () {
var inputTime = $('#chatinput time');
@@ -554,7 +610,7 @@ chat.setupTime = function () {
/**
* Handles tab completion in chat input.
*
- * @function chat.handleTabCompletion
+ * @function handleTabCompletion
*/
chat.handleTabCompletion = function () {
var el = $('#chatinput input');
@@ -595,7 +651,7 @@ chat.handleTabCompletion = function () {
/**
* Posts a chat message to the currently active chat tab.
*
- * @function chat.postMsg
+ * @function postMsg
*/
chat.postMsg = function () {
var c = chat.getActive();
@@ -613,7 +669,7 @@ chat.postMsg = function () {
/**
* Sets up the chat message posting functionality.
*
- * @function chat.setupPosting
+ * @function setupPosting
*/
chat.setupPosting = function () {
if (!window.isSmartphone()) {
@@ -642,4 +698,58 @@ chat.setupPosting = function () {
});
};
+/**
+ * Legacy function for rendering chat messages. Used for backward compatibility with plugins.
+ *
+ * @deprecated
+ * @function renderMsg
+ * @param {string} msg - The chat message.
+ * @param {string} nick - The nickname of the player who sent the message.
+ * @param {number} time - The timestamp of the message.
+ * @param {string} team - The team of the player who sent the message.
+ * @param {boolean} msgToPlayer - Flag indicating if the message is directed to the player.
+ * @param {boolean} systemNarrowcast - Flag indicating if the message is a system narrowcast.
+ * @returns {string} The HTML string representing a chat message row.
+ */
+chat.renderMsg = function (msg, nick, time, team, msgToPlayer, systemNarrowcast) {
+ // Imitating data usually derived from processing raw chat data
+ var fakeData = {
+ guid: 'legacyguid-' + Math.random(),
+ time: time,
+ public: !systemNarrowcast,
+ secure: systemNarrowcast,
+ alert: msgToPlayer,
+ msgToPlayer: msgToPlayer,
+ type: systemNarrowcast ? 'SYSTEM_NARROWCAST' : 'PLAYER_GENERATED',
+ narrowcast: systemNarrowcast,
+ auto: false, // Assuming the message is player-generated if it's not a system broadcast
+ team: team,
+ player: {
+ name: nick,
+ team: team,
+ },
+ markup: [
+ ['TEXT', { plain: msg }], // A simple message with no special markup
+ ],
+ };
+
+ // Use existing IITC functions to render a chat message row
+ return IITC.comm.renderMsgRow(fakeData);
+};
+
+/**
+ * Legacy function for converts a chat tab name to its corresponding COMM channel name.
+ * Used for backward compatibility with plugins.
+ *
+ * @deprecated
+ * @function tabToChannel
+ * @param {string} tab - The name of the chat tab.
+ * @returns {string} The corresponding channel name ('faction', 'alerts', or 'all').
+ */
+chat.tabToChannel = function (tab) {
+ if (tab === 'faction') return 'faction';
+ if (tab === 'alerts') return 'alerts';
+ return 'all';
+};
+
/* global log, PLAYER, L, IITC, app */
diff --git a/core/code/comm.js b/core/code/comm.js
index f5219143c..2414e75bc 100644
--- a/core/code/comm.js
+++ b/core/code/comm.js
@@ -7,6 +7,7 @@
/**
* @type {chat.ChannelDescription[]}
+ * @memberof IITC.comm
*/
var _channels = [
{
@@ -46,6 +47,7 @@ var _channels = [
* Holds data related to each intel channel.
*
* @type {Object}
+ * @memberof IITC.comm
*/
var _channelsData = {};
@@ -67,6 +69,54 @@ function _initChannelData(id) {
delete _channelsData[id].newestGUID;
}
+/**
+ * Template of portal link in comm.
+ * @type {String}
+ * @memberof IITC.comm
+ */
+let portalTemplate =
+ '{{ portal_name }}';
+/**
+ * Template for time cell.
+ * @type {String}
+ * @memberof IITC.comm
+ */
+let timeCellTemplate = '
';
+
+/**
+ * Returns the coordinates for the message to be sent, default is the center of the map.
+ *
+ * @function IITC.comm.getLatLngForSendingMessage
+ * @returns {L.LatLng}
+ */
+function getLatLngForSendingMessage() {
+ return map.getCenter();
+}
+
/**
* Updates the oldest and newest message timestamps and GUIDs in the chat storage.
*
@@ -207,7 +257,7 @@ function _writeDataToHash(newData, storageHash, isOlderMsgs, isAscendingOrder) {
function sendChatMessage(tab, msg) {
if (tab !== 'all' && tab !== 'faction') return;
- var latlng = map.getCenter();
+ const latlng = IITC.comm.getLatLngForSendingMessage();
var data = {
message: msg,
@@ -239,12 +289,16 @@ var _oldBBox = null;
* @private
* @param {string} channel - The chat channel.
* @param {boolean} getOlderMsgs - Flag to determine if older messages are being requested.
+ * @param args=undefined - Used for backward compatibility when calling a function with three arguments.
* @returns {Object} The generated post data.
*/
-function _genPostData(channel, getOlderMsgs) {
+function _genPostData(channel, getOlderMsgs, ...args) {
if (typeof channel !== 'string') {
throw new Error('API changed: isFaction flag now a channel string - all, faction, alerts');
}
+ if (args.length === 1) {
+ getOlderMsgs = args[0];
+ }
var b = window.clampLatLngBounds(map.getBounds());
@@ -430,20 +484,46 @@ function renderText(text) {
return content.html().autoLink();
}
+/**
+ * List of transformations for portal names used in chat.
+ * Each transformation function takes the portal markup object and returns a transformed name.
+ * If a transformation does not apply, the original name is returned.
+ *
+ * @const IITC.comm.portalNameTransformations
+ * @example
+ * // Adding a transformation that appends the portal location to its name
+ * portalNameTransformations.push((markup) => {
+ * const latlng = `${markup.latE6 / 1E6},${markup.lngE6 / 1E6}`; // Convert E6 format to decimal
+ * return `[${latlng}] ${markup.name}`;
+ * });
+ */
+const portalNameTransformations = [
+ // Transformation for 'US Post Office'
+ (markup) => {
+ if (markup.name === 'US Post Office') {
+ const address = markup.address.split(',');
+ return 'USPS: ' + address[0];
+ }
+ return markup.name;
+ },
+];
+
/**
* Overrides portal names used repeatedly in chat, such as 'US Post Office', with more specific names.
+ * Applies a series of transformations to the portal name based on the portal markup.
*
* @function IITC.comm.getChatPortalName
* @param {Object} markup - An object containing portal markup, including the name and address.
* @returns {string} The processed portal name.
*/
function getChatPortalName(markup) {
- var name = markup.name;
- if (name === 'US Post Office') {
- var address = markup.address.split(',');
- name = 'USPS: ' + address[0];
- }
- return name;
+ // Use reduce to apply each transformation to the data
+ const transformedData = portalNameTransformations.reduce((initialMarkup, transform) => {
+ const updatedName = transform(initialMarkup);
+ return { ...initialMarkup, name: updatedName };
+ }, markup);
+
+ return transformedData.name;
}
/**
@@ -454,11 +534,17 @@ function getChatPortalName(markup) {
* @returns {string} HTML string of the portal link.
*/
function renderPortal(portal) {
- var lat = portal.latE6 / 1e6,
- lng = portal.lngE6 / 1e6;
- var perma = window.makePermalink([lat, lng]);
- var js = 'window.selectPortalByLatLng(' + lat + ', ' + lng + ');return false';
- return '' + IITC.comm.getChatPortalName(portal) + '';
+ const lat = portal.latE6 / 1e6;
+ const lng = portal.lngE6 / 1e6;
+ const permalink = window.makePermalink([lat, lng]);
+ const portalName = IITC.comm.getChatPortalName(portal);
+
+ return IITC.comm.portalTemplate
+ .replace('{{ lat }}', lat.toString())
+ .replace('{{ lng }}', lng.toString())
+ .replace('{{ title }}', portal.address)
+ .replace('{{ url }}', permalink)
+ .replace('{{ portal_name }}', portalName);
}
/**
@@ -561,58 +647,102 @@ function renderMarkup(markup) {
}
/**
- * Transforms a the markup array into an older, more straightforward format for easier understanding.
- *
- * May be used to build an entirely new markup to be rendered without altering the original one.
+ * List of transformations to be applied to the message data.
+ * Each transformation function takes the full message data object and returns the transformed markup.
+ * The default transformations aim to convert the message markup into an older, more straightforward format,
+ * facilitating easier understanding and backward compatibility with plugins expecting the older message format.
*
- * @function IITC.comm.transformMessage
- * @param {Object} data - The data for the message, including time, player, and message content.
- * @returns {Array} The transformed markup array with a simplified structure.
+ * @const IITC.comm.messageTransformFunctions
+ * @example
+ * // Adding a new transformation function to the array
+ * // This new function adds a "new" prefix to the player's plain text if the player is from the RESISTANCE team
+ * messageTransformFunctions.push((data) => {
+ * const markup = data.markup;
+ * if (markup.length > 2 && markup[0][0] === 'PLAYER' && markup[0][1].team === 'RESISTANCE') {
+ * markup[1][1].plain = 'new ' + markup[1][1].plain;
+ * }
+ * return markup;
+ * });
*/
-function transformMessage(data) {
- // Make a copy of the markup array to avoid modifying the original input
- let newMarkup = JSON.parse(JSON.stringify(data.markup));
-
- // Collapse + "Link"/"Field". Example: "Agent destroyed the Link ..."
- if (newMarkup.length > 4) {
- if (newMarkup[3][0] === 'FACTION' && newMarkup[4][0] === 'TEXT' && (newMarkup[4][1].plain === ' Link ' || newMarkup[4][1].plain === ' Control Field @')) {
- newMarkup[4][1].team = newMarkup[3][1].team;
- newMarkup.splice(3, 1);
+const messageTransformFunctions = [
+ // Collapse + "Link"/"Field".
+ (data) => {
+ const markup = data.markup;
+ if (
+ markup.length > 4 &&
+ markup[3][0] === 'FACTION' &&
+ markup[4][0] === 'TEXT' &&
+ (markup[4][1].plain === ' Link ' || markup[4][1].plain === ' Control Field @')
+ ) {
+ markup[4][1].team = markup[3][1].team;
+ markup.splice(3, 1);
}
- }
-
+ return markup;
+ },
// Skip "Agent " at the beginning
- if (newMarkup.length > 1) {
- if (newMarkup[0][0] === 'TEXT' && newMarkup[0][1].plain === 'Agent ' && newMarkup[1][0] === 'PLAYER') {
- newMarkup.splice(0, 2);
+ (data) => {
+ const markup = data.markup;
+ if (markup.length > 1 && markup[0][0] === 'TEXT' && markup[0][1].plain === 'Agent ' && markup[1][0] === 'PLAYER') {
+ markup.splice(0, 2);
}
- }
-
+ return markup;
+ },
// Skip " agent " at the beginning
- if (newMarkup.length > 2) {
- if (newMarkup[0][0] === 'FACTION' && newMarkup[1][0] === 'TEXT' && newMarkup[1][1].plain === ' agent ' && newMarkup[2][0] === 'PLAYER') {
- newMarkup.splice(0, 3);
+ (data) => {
+ const markup = data.markup;
+ if (markup.length > 2 && markup[0][0] === 'FACTION' && markup[1][0] === 'TEXT' && markup[1][1].plain === ' agent ' && markup[2][0] === 'PLAYER') {
+ markup.splice(0, 3);
}
- }
+ return markup;
+ },
+];
- return newMarkup;
-}
+/**
+ * Applies transformations to the markup array based on the transformations defined in
+ * the {@link IITC.comm.messageTransformFunctions} array.
+ * Assumes all transformations return a new markup array.
+ * May be used to build an entirely new markup to be rendered without altering the original one.
+ *
+ * @function IITC.comm.transformMessage
+ * @param {Object} data - The data for the message, including time, player, and message content.
+ * @returns {Object} The transformed markup array.
+ */
+const transformMessage = (data) => {
+ const initialData = JSON.parse(JSON.stringify(data));
+
+ // Use reduce to apply each transformation to the data
+ const transformedData = messageTransformFunctions.reduce((data, transform) => {
+ const updatedMarkup = transform(data);
+ return { ...data, markup: updatedMarkup };
+ }, initialData);
+
+ return transformedData.markup;
+};
/**
* Renders a cell in the chat table to display the time a message was sent.
* Formats the time and adds it to a