snapshot of https://github.com/mattermost/mattermost.git (master, 2026-09-16; blobs > 131072B omitted)
Some checks failed
Server CI / Postgres (shard 0) (push) Has been skipped
Server CI / Postgres (shard 3) (push) Has been skipped
BuildEnv Docker Image / build-image (push) Failing after 4s
BuildEnv Docker Image / build-image-fips (push) Failing after 4s
Migration Review & Release Notes / Generate migration review & release notes (push) Failing after 3s
Server CI / Build Environment (push) Failing after 3s
Server CI / Postgres (shard 1) (push) Has been skipped
Tools CI / check-style (mattermost-govet) (push) Failing after 4s
Server CI / Postgres (shard 2) (push) Has been skipped
Tools CI / check-style (mmgotool) (push) Failing after 3s
Server CI / Elasticsearch v8 Compatibility (push) Has been skipped
Server CI / OpenSearch v2 Compatibility (push) Has been skipped
Server CI / Postgres FIPS (shard 0) (push) Has been skipped
Tools CI / Test (mattermost-govet) (push) Failing after 3s
Server CI / Postgres FIPS (shard 1) (push) Has been skipped
Server CI / Postgres FIPS (shard 2) (push) Has been skipped
Tools CI / Test (mmgotool) (push) Failing after 3s
Server CI / Postgres FIPS (shard 3) (push) Has been skipped
Server CI / Run mmctl tests (push) Has been skipped
Server CI / Run mmctl tests (FIPS) (push) Has been skipped
Server CI / Merge Postgres Test Results (push) Has been skipped
Server CI / Merge Postgres FIPS Test Results (push) Has been skipped
Server CI / Check backport migrations (push) Has been skipped
Server CI / Check generated files (push) Has been skipped
Server CI / check-style (push) Has been skipped
Server CI / Vet API (push) Has been skipped
Server CI / Build mattermost server app (push) Has been skipped
Server CI / Server CI Complete (push) Failing after 2s
Server CI / Server CI Artifacts (push) Has been skipped
Server CI / Sentry Upload (push) Has been skipped
Server CI / Server CI Report (push) Failing after 5m1s
Server CI Nightly Race / Race Detector (push) Has been skipped
CodeQL / Analyze (go) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Webapp CI Cache Warm / Warm Webapp node_modules Cache (push) Has been cancelled
E2E CI Cache Warm / Warm E2E npm Registry Cache (push) Has been cancelled
API / build (push) Has been cancelled
Web App CI / check-types (push) Has been cancelled
Web App CI / check-lint (push) Has been cancelled
Web App CI / check-i18n (push) Has been cancelled
Web App CI / check-external-links (push) Has been cancelled
Web App CI / test (platform) (push) Has been cancelled
Web App CI / test (mattermost-redux) (push) Has been cancelled
Web App CI / test (channels shard 1/4) (push) Has been cancelled
Web App CI / test (channels shard 2/4) (push) Has been cancelled
Web App CI / test (channels shard 3/4) (push) Has been cancelled
Web App CI / test (channels shard 4/4) (push) Has been cancelled
Web App CI / upload-coverage (push) Has been cancelled
Web App CI / build (push) Has been cancelled
YAML Lint / yamllint (push) Has been cancelled
Push mirrored docker images / cd/Push mirrored docker images (push) Has been cancelled
docs-cd / Build and deploy docs (push) Has been cancelled
Docs CI / build (push) Has been cancelled
E2E Cache Warm: Cypress deps / Warm Cypress deps cache (push) Has been cancelled
Scorecards supply-chain security / Scorecard analysis (push) Has been cancelled
Server CI Weekly / Postgres FIPS (push) Has been skipped
Server CI Weekly / Run mmctl tests (FIPS) (push) Has been skipped
Server CI Weekly / Postgres with binary parameters (push) Has been skipped
Server CI Weekly / Build Environment (push) Failing after 1s
Server CI Cache Warm / Warm Go Module and Build Cache (push) Failing after 2s
Server CI Nightly Race / Build Environment (push) Failing after 1s
Some checks failed
Server CI / Postgres (shard 0) (push) Has been skipped
Server CI / Postgres (shard 3) (push) Has been skipped
BuildEnv Docker Image / build-image (push) Failing after 4s
BuildEnv Docker Image / build-image-fips (push) Failing after 4s
Migration Review & Release Notes / Generate migration review & release notes (push) Failing after 3s
Server CI / Build Environment (push) Failing after 3s
Server CI / Postgres (shard 1) (push) Has been skipped
Tools CI / check-style (mattermost-govet) (push) Failing after 4s
Server CI / Postgres (shard 2) (push) Has been skipped
Tools CI / check-style (mmgotool) (push) Failing after 3s
Server CI / Elasticsearch v8 Compatibility (push) Has been skipped
Server CI / OpenSearch v2 Compatibility (push) Has been skipped
Server CI / Postgres FIPS (shard 0) (push) Has been skipped
Tools CI / Test (mattermost-govet) (push) Failing after 3s
Server CI / Postgres FIPS (shard 1) (push) Has been skipped
Server CI / Postgres FIPS (shard 2) (push) Has been skipped
Tools CI / Test (mmgotool) (push) Failing after 3s
Server CI / Postgres FIPS (shard 3) (push) Has been skipped
Server CI / Run mmctl tests (push) Has been skipped
Server CI / Run mmctl tests (FIPS) (push) Has been skipped
Server CI / Merge Postgres Test Results (push) Has been skipped
Server CI / Merge Postgres FIPS Test Results (push) Has been skipped
Server CI / Check backport migrations (push) Has been skipped
Server CI / Check generated files (push) Has been skipped
Server CI / check-style (push) Has been skipped
Server CI / Vet API (push) Has been skipped
Server CI / Build mattermost server app (push) Has been skipped
Server CI / Server CI Complete (push) Failing after 2s
Server CI / Server CI Artifacts (push) Has been skipped
Server CI / Sentry Upload (push) Has been skipped
Server CI / Server CI Report (push) Failing after 5m1s
Server CI Nightly Race / Race Detector (push) Has been skipped
CodeQL / Analyze (go) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Webapp CI Cache Warm / Warm Webapp node_modules Cache (push) Has been cancelled
E2E CI Cache Warm / Warm E2E npm Registry Cache (push) Has been cancelled
API / build (push) Has been cancelled
Web App CI / check-types (push) Has been cancelled
Web App CI / check-lint (push) Has been cancelled
Web App CI / check-i18n (push) Has been cancelled
Web App CI / check-external-links (push) Has been cancelled
Web App CI / test (platform) (push) Has been cancelled
Web App CI / test (mattermost-redux) (push) Has been cancelled
Web App CI / test (channels shard 1/4) (push) Has been cancelled
Web App CI / test (channels shard 2/4) (push) Has been cancelled
Web App CI / test (channels shard 3/4) (push) Has been cancelled
Web App CI / test (channels shard 4/4) (push) Has been cancelled
Web App CI / upload-coverage (push) Has been cancelled
Web App CI / build (push) Has been cancelled
YAML Lint / yamllint (push) Has been cancelled
Push mirrored docker images / cd/Push mirrored docker images (push) Has been cancelled
docs-cd / Build and deploy docs (push) Has been cancelled
Docs CI / build (push) Has been cancelled
E2E Cache Warm: Cypress deps / Warm Cypress deps cache (push) Has been cancelled
Scorecards supply-chain security / Scorecard analysis (push) Has been cancelled
Server CI Weekly / Postgres FIPS (push) Has been skipped
Server CI Weekly / Run mmctl tests (FIPS) (push) Has been skipped
Server CI Weekly / Postgres with binary parameters (push) Has been skipped
Server CI Weekly / Build Environment (push) Failing after 1s
Server CI Cache Warm / Warm Go Module and Build Cache (push) Failing after 2s
Server CI Nightly Race / Build Environment (push) Failing after 1s
This commit is contained in:
1
webapp/channels/build/.gitignore
vendored
Normal file
1
webapp/channels/build/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
test-results.xml
|
||||
3
webapp/channels/build/Dockerfile
Normal file
3
webapp/channels/build/Dockerfile
Normal file
@@ -0,0 +1,3 @@
|
||||
FROM node:14.16
|
||||
RUN apt-get update && apt-get install -y make gcc nasm libpng-dev
|
||||
CMD [ "node" ]
|
||||
2865
webapp/channels/build/emoji/additional_shortnames.json
Normal file
2865
webapp/channels/build/emoji/additional_shortnames.json
Normal file
File diff suppressed because it is too large
Load Diff
502
webapp/channels/build/emoji/make_emojis.mjs
Executable file
502
webapp/channels/build/emoji/make_emojis.mjs
Executable file
@@ -0,0 +1,502 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
/*
|
||||
* This script will generate the emoji files for both the webapp and server to use emojis from 'emoji-datasource' npm package
|
||||
* It will generate the following files:
|
||||
* '<rootDir>/webapp/channels/src/utils/emoji.ts'
|
||||
* '<rootDir>/webapp/channels/src/sass/components/_emojisprite.scss'
|
||||
* '<rootDir>/webapp/channels/src/utils/emoji.json'
|
||||
* '<rootDir>/server/public/model/emoji_data.go',
|
||||
*
|
||||
* For help on how to use this script, run:
|
||||
* npm run make-emojis -- --help
|
||||
*/
|
||||
|
||||
import * as fs from 'node:fs';
|
||||
import * as fsPromise from 'node:fs/promises';
|
||||
import path from 'node:path';
|
||||
import * as url from 'node:url';
|
||||
|
||||
import chalk from 'chalk';
|
||||
import jsonCategories from 'emoji-datasource/categories.json' assert {type: 'json'};
|
||||
import jsonData from 'emoji-datasource/emoji.json' assert {type: 'json'};
|
||||
import yargs from 'yargs';
|
||||
|
||||
import additionalShortnames from './additional_shortnames.json' assert {type: 'json'};
|
||||
|
||||
const EMOJI_SIZE = 64;
|
||||
const EMOJI_SIZE_PADDED = EMOJI_SIZE + 2; // 1px per side
|
||||
const EMOJI_DEFAULT_SKIN = 'default';
|
||||
const endResults = [];
|
||||
|
||||
const currentDir = path.dirname(url.fileURLToPath(import.meta.url));
|
||||
const rootDir = path.resolve(currentDir, '..', '..', '..', '..');
|
||||
const serverRootDir = path.resolve(rootDir, 'server');
|
||||
const webappRootDir = path.resolve(rootDir, 'webapp');
|
||||
|
||||
const argv = yargs(process.argv.slice(1)).
|
||||
scriptName('make-emojis').
|
||||
usage('Usage : npm run $0 -- [args]').
|
||||
example('npm run $0 -- --excluded-emoji-file ./excludedEmojis.txt', 'removes mentioned emojis from the app').
|
||||
option('excluded-emoji-file', {
|
||||
description: 'Path to a file containing emoji short names to exclude',
|
||||
type: 'string',
|
||||
}).
|
||||
help().
|
||||
epilog('Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.').
|
||||
argv;
|
||||
|
||||
const argsExcludedEmojiFile = argv['excluded-emoji-file'];
|
||||
|
||||
function log(level = '', text) {
|
||||
if (level === 'info') {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(chalk.cyan(`[INFO]: ${text}`));
|
||||
} else if (level === 'warn') {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(chalk.yellow(`[WARN]: ${text}`));
|
||||
} else if (level === 'error') {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(chalk.red(`[ERRO]: ${text}`));
|
||||
} else if (level === 'success') {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(chalk.green(`[SUCC]: ${text}`));
|
||||
} else {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(text);
|
||||
}
|
||||
}
|
||||
|
||||
function writeToFileAndPrint(fileName, filePath, data) {
|
||||
const promise = fsPromise.writeFile(filePath, data, writeOptions);
|
||||
|
||||
promise.then(() => {
|
||||
log('info', `"${fileName}" generated successfully in "${filePath}"`);
|
||||
}).catch((err) => {
|
||||
log('error', `Failed to generate "${fileName}": ${err}`);
|
||||
});
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
function copyFileAndPrint(source, destination, fileName, print = true) {
|
||||
const promise = fsPromise.copyFile(source, destination);
|
||||
|
||||
promise.then(() => {
|
||||
if (print) {
|
||||
log('info', `"${fileName}" copied successfully to "${destination}"`);
|
||||
}
|
||||
}).catch((err) => {
|
||||
log('error', `Failed to copy "${fileName}": ${err}`);
|
||||
});
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
function normalizeCategoryName(category) {
|
||||
return category.toLowerCase().replace(' & ', '-');
|
||||
}
|
||||
|
||||
// Copy emoji images from 'emoji-datasource-apple'
|
||||
const emojiDataSourceDir = path.resolve(webappRootDir, `node_modules/emoji-datasource-apple/img/apple/${EMOJI_SIZE}/`);
|
||||
const emojiImagesDir = path.resolve(webappRootDir, 'channels', 'src', 'images', 'emoji');
|
||||
const readDirPromise = fsPromise.readdir(emojiDataSourceDir);
|
||||
endResults.push(readDirPromise);
|
||||
readDirPromise.then((images) => {
|
||||
for (const imageFile of images) {
|
||||
endResults.push(copyFileAndPrint(path.join(emojiDataSourceDir, imageFile), path.join(emojiImagesDir, imageFile), imageFile, false));
|
||||
}
|
||||
});
|
||||
|
||||
// Missing emojis from Apple emoji set ["medical_symbol", "male_sign", and "female_sign"]
|
||||
// @see https://github.com/iamcal/emoji-data#image-sources
|
||||
const missingEmojis = ['2640-fe0f', '2642-fe0f', '2695-fe0f'];
|
||||
|
||||
// Copy the missing from google emoji set
|
||||
const missingEmojiDataSourceDir = path.resolve(webappRootDir, `node_modules/emoji-datasource-google/img/google/${EMOJI_SIZE}/`);
|
||||
const readMissingDirPromise = fsPromise.readdir(missingEmojiDataSourceDir);
|
||||
endResults.push(readMissingDirPromise);
|
||||
readMissingDirPromise.then(() => {
|
||||
for (const missingEmoji of missingEmojis) {
|
||||
endResults.push(
|
||||
copyFileAndPrint(path.join(missingEmojiDataSourceDir, `${missingEmoji}.png`), path.join(emojiImagesDir, `${missingEmoji}.png`), `Missed ${missingEmoji}`));
|
||||
}
|
||||
});
|
||||
|
||||
// Copy mattermost emoji image
|
||||
const webappImagesDir = path.resolve(webappRootDir, 'channels', 'src', 'images');
|
||||
endResults.push(copyFileAndPrint(path.resolve(webappImagesDir, 'icon64x64.png'), path.resolve(webappImagesDir, 'emoji/mattermost.png'), 'mattermost-emoji'));
|
||||
|
||||
const sheetSource = path.resolve(webappRootDir, `node_modules/emoji-datasource-apple/img/apple/sheets/${EMOJI_SIZE}.png`);
|
||||
const sheetAbsoluteFile = path.resolve(webappRootDir, 'channels', 'src', 'images/emoji-sheets/apple-sheet.png');
|
||||
const sheetFile = 'images/emoji-sheets/apple-sheet.png';
|
||||
|
||||
// Copy sheet image
|
||||
endResults.push(copyFileAndPrint(sheetSource, sheetAbsoluteFile, 'emoji-sheet'));
|
||||
|
||||
// we'll load it as a two dimensional array so we can generate a Map out of it
|
||||
const emojiIndicesByAlias = [];
|
||||
const emojiIndicesByUnicode = [];
|
||||
const emojiIndicesByCategory = new Map();
|
||||
const emojiIndicesByCategoryAndSkin = new Map();
|
||||
const emojiIndicesByCategoryNoSkin = new Map();
|
||||
const categoryNamesSet = new Set();
|
||||
const emojiImagesByAlias = [];
|
||||
const emojiFilePositions = new Map();
|
||||
const skinCodes = {
|
||||
'1F3FB': 'light_skin_tone',
|
||||
'1F3FC': 'medium_light_skin_tone',
|
||||
'1F3FD': 'medium_skin_tone',
|
||||
'1F3FE': 'medium_dark_skin_tone',
|
||||
'1F3FF': 'dark_skin_tone',
|
||||
default: 'default',
|
||||
};
|
||||
const skinNames = {
|
||||
'1F3FB': 'LIGHT SKIN TONE',
|
||||
'1F3FC': 'MEDIUM LIGHT SKIN TONE',
|
||||
'1F3FD': 'MEDIUM SKIN TONE',
|
||||
'1F3FE': 'MEDIUM DARK SKIN TONE',
|
||||
'1F3FF': 'DARK SKIN TONE',
|
||||
};
|
||||
const control = new AbortController();
|
||||
const writeOptions = {
|
||||
encoding: 'utf8',
|
||||
signal: control.signal,
|
||||
};
|
||||
|
||||
// Extract excluded emoji shortnames as an array
|
||||
const excludedEmoji = [];
|
||||
if (argsExcludedEmojiFile) {
|
||||
fs.readFileSync(path.normalize(argsExcludedEmojiFile), 'utf-8').split(/\r?\n/).forEach((line) => {
|
||||
excludedEmoji.push(line);
|
||||
});
|
||||
log('warn', `The following emoji(s) will be excluded from the webapp: \n${excludedEmoji}\n`);
|
||||
}
|
||||
|
||||
// Remove unwanted emoji
|
||||
const filteredEmojiJson = jsonData.filter((element) => !excludedEmoji.some((e) => element.short_names.includes(e)));
|
||||
|
||||
function generateEmojiSkinVariations(emoji) {
|
||||
if (!emoji.skin_variations) {
|
||||
return [];
|
||||
}
|
||||
return Object.keys(emoji.skin_variations).map((skinCode) => {
|
||||
// if skin codes ever change this will produce a null_light_skin_tone
|
||||
const skins = skinCode.split('-');
|
||||
const skinShortName = skins.map((code) => skinCodes[code]).join('_');
|
||||
const skinName = skins.map((code) => skinNames[code]).join(', ');
|
||||
const variation = {...emoji.skin_variations[skinCode]};
|
||||
variation.short_name = `${emoji.short_name}_${skinShortName}`;
|
||||
variation.short_names = emoji.short_names.map((alias) => `${alias}_${skinShortName}`);
|
||||
variation.name = `${emoji.name}: ${skinName}`;
|
||||
variation.category = emoji.category;
|
||||
variation.skins = skins;
|
||||
return variation;
|
||||
});
|
||||
}
|
||||
|
||||
// populate skin tones as full emojis
|
||||
const fullEmoji = [...filteredEmojiJson];
|
||||
filteredEmojiJson.forEach((emoji) => {
|
||||
const variations = generateEmojiSkinVariations(emoji);
|
||||
fullEmoji.push(...variations);
|
||||
});
|
||||
|
||||
// add old shortnames to maintain backwards compatibility with gemoji
|
||||
fullEmoji.forEach((emoji) => {
|
||||
if (emoji.short_name in additionalShortnames) {
|
||||
emoji.short_names.push(...additionalShortnames[emoji.short_name]);
|
||||
}
|
||||
});
|
||||
|
||||
// add built-in custom emojis
|
||||
fullEmoji.push({
|
||||
id: 'mattermost',
|
||||
name: 'mattermost',
|
||||
unified: '',
|
||||
image: 'mattermost.png',
|
||||
short_name: 'mattermost',
|
||||
short_names: ['mattermost'],
|
||||
category: 'custom',
|
||||
});
|
||||
|
||||
fullEmoji.sort((emojiA, emojiB) => emojiA.sort_order - emojiB.sort_order);
|
||||
|
||||
function addIndexToMap(emojiMap, key, ...indexes) {
|
||||
const newList = emojiMap.get(key) || [];
|
||||
newList.push(...indexes);
|
||||
emojiMap.set(key, newList);
|
||||
}
|
||||
|
||||
const skinset = new Set();
|
||||
fullEmoji.forEach((emoji, index) => {
|
||||
if (emoji.unified) {
|
||||
emojiIndicesByUnicode.push([emoji.unified.toLowerCase(), index]);
|
||||
}
|
||||
|
||||
const safeCat = normalizeCategoryName(emoji.category);
|
||||
emoji.category = safeCat;
|
||||
addIndexToMap(emojiIndicesByCategory, safeCat, index);
|
||||
if (emoji.skins || emoji.skin_variations) {
|
||||
const skin = (emoji.skins && emoji.skins[0]) || EMOJI_DEFAULT_SKIN;
|
||||
skinset.add(skin);
|
||||
const categoryBySkin = emojiIndicesByCategoryAndSkin.get(skin) || new Map();
|
||||
addIndexToMap(categoryBySkin, safeCat, index);
|
||||
emojiIndicesByCategoryAndSkin.set(skin, categoryBySkin);
|
||||
} else {
|
||||
addIndexToMap(emojiIndicesByCategoryNoSkin, safeCat, index);
|
||||
}
|
||||
categoryNamesSet.add(safeCat);
|
||||
emojiIndicesByAlias.push(...emoji.short_names.map((alias) => [alias, index]));
|
||||
const file = emoji.image.split('.')[0];
|
||||
emoji.fileName = emoji.image;
|
||||
emoji.image = file;
|
||||
|
||||
if (emoji.category !== 'custom') {
|
||||
let x = emoji.sheet_x * EMOJI_SIZE_PADDED;
|
||||
if (x !== 0) {
|
||||
x += 'px';
|
||||
}
|
||||
let y = emoji.sheet_y * EMOJI_SIZE_PADDED;
|
||||
if (y !== 0) {
|
||||
y += 'px';
|
||||
}
|
||||
emojiFilePositions.set(file, `-${x} -${y};`);
|
||||
}
|
||||
|
||||
emojiImagesByAlias.push(...emoji.short_names.map((alias) => `"${alias}": "${file}"`));
|
||||
});
|
||||
|
||||
function trimPropertiesFromEmoji(emoji) {
|
||||
if (Object.hasOwn(emoji, 'non_qualified')) {
|
||||
Reflect.deleteProperty(emoji, 'non_qualified');
|
||||
}
|
||||
|
||||
if (Object.hasOwn(emoji, 'docomo')) {
|
||||
Reflect.deleteProperty(emoji, 'docomo');
|
||||
}
|
||||
|
||||
if (Object.hasOwn(emoji, 'au')) {
|
||||
Reflect.deleteProperty(emoji, 'au');
|
||||
}
|
||||
|
||||
if (Object.hasOwn(emoji, 'softbank')) {
|
||||
Reflect.deleteProperty(emoji, 'softbank');
|
||||
}
|
||||
|
||||
if (Object.hasOwn(emoji, 'google')) {
|
||||
Reflect.deleteProperty(emoji, 'google');
|
||||
}
|
||||
|
||||
if (Object.hasOwn(emoji, 'sheet_x')) {
|
||||
Reflect.deleteProperty(emoji, 'sheet_x');
|
||||
}
|
||||
|
||||
if (Object.hasOwn(emoji, 'sheet_y')) {
|
||||
Reflect.deleteProperty(emoji, 'sheet_y');
|
||||
}
|
||||
|
||||
if (Object.hasOwn(emoji, 'added_in')) {
|
||||
Reflect.deleteProperty(emoji, 'added_in');
|
||||
}
|
||||
|
||||
if (Object.hasOwn(emoji, 'has_img_apple')) {
|
||||
Reflect.deleteProperty(emoji, 'has_img_apple');
|
||||
}
|
||||
|
||||
if (Object.hasOwn(emoji, 'has_img_google')) {
|
||||
Reflect.deleteProperty(emoji, 'has_img_google');
|
||||
}
|
||||
|
||||
if (Object.hasOwn(emoji, 'has_img_twitter')) {
|
||||
Reflect.deleteProperty(emoji, 'has_img_twitter');
|
||||
}
|
||||
|
||||
if (Object.hasOwn(emoji, 'has_img_facebook')) {
|
||||
Reflect.deleteProperty(emoji, 'has_img_facebook');
|
||||
}
|
||||
|
||||
if (Object.hasOwn(emoji, 'source_index')) {
|
||||
Reflect.deleteProperty(emoji, 'source_index');
|
||||
}
|
||||
|
||||
if (Object.hasOwn(emoji, 'sort_order')) {
|
||||
Reflect.deleteProperty(emoji, 'sort_order');
|
||||
}
|
||||
|
||||
if (Object.hasOwn(emoji, 'subcategory')) {
|
||||
Reflect.deleteProperty(emoji, 'subcategory');
|
||||
}
|
||||
|
||||
if (Object.hasOwn(emoji, 'image')) {
|
||||
Reflect.deleteProperty(emoji, 'image');
|
||||
}
|
||||
|
||||
if (Object.hasOwn(emoji, 'fileName')) {
|
||||
Reflect.deleteProperty(emoji, 'fileName');
|
||||
}
|
||||
|
||||
return emoji;
|
||||
}
|
||||
|
||||
// Removed properties that are not needed for the webapp
|
||||
const trimmedDownEmojis = fullEmoji.map((emoji) => trimPropertiesFromEmoji(emoji));
|
||||
|
||||
// Create the emoji.json file
|
||||
const webappUtilsEmojiDir = path.resolve(webappRootDir, 'channels', 'src', 'utils', 'emoji.json');
|
||||
endResults.push(writeToFileAndPrint('emoji.json', webappUtilsEmojiDir, JSON.stringify(trimmedDownEmojis, null, 4)));
|
||||
|
||||
const categoryList = Object.keys(jsonCategories).filter((item) => item !== 'Component').map(normalizeCategoryName);
|
||||
const categoryNames = ['recent', ...categoryList, 'custom'];
|
||||
|
||||
const writeableSkinCategories = [];
|
||||
const skinnedCats = [];
|
||||
for (const skin of emojiIndicesByCategoryAndSkin.keys()) {
|
||||
writeableSkinCategories.push(`['${skin}', new Map(${JSON.stringify(Array.from(emojiIndicesByCategoryAndSkin.get(skin)))})]`);
|
||||
skinnedCats.push(`['${skin}', genSkinnedCategories('${skin}')]`);
|
||||
}
|
||||
|
||||
// Generate contents of emoji.ts out of the emoji.json parsing we did earlier
|
||||
const emojiJSX = `// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
// This file is automatically generated via \`/webapp/channels/build/make_emojis.mjs\`. Do not modify it manually.
|
||||
|
||||
/* eslint-disable */
|
||||
|
||||
import memoize from 'memoize-one';
|
||||
|
||||
import emojis from 'utils/emoji.json';
|
||||
|
||||
import spriteSheet from '${sheetFile}';
|
||||
|
||||
export const Emojis = emojis;
|
||||
|
||||
export const EmojiIndicesByAlias = new Map(${JSON.stringify(emojiIndicesByAlias)});
|
||||
|
||||
export const EmojiIndicesByUnicode = new Map(${JSON.stringify(emojiIndicesByUnicode)});
|
||||
|
||||
export const CategoryNames = ${JSON.stringify(categoryNames)};
|
||||
|
||||
const AllEmojiIndicesByCategory = new Map(${JSON.stringify(Array.from(emojiIndicesByCategory))});
|
||||
|
||||
const EmojiIndicesByCategoryAndSkin = new Map([${writeableSkinCategories.join(', ')}]);
|
||||
const EmojiIndicesByCategoryNoSkin = new Map(${JSON.stringify(Array.from(emojiIndicesByCategoryNoSkin))});
|
||||
|
||||
const skinCodes = ${JSON.stringify(skinCodes)};
|
||||
|
||||
// Generate the list of indices that belong to each category by an specified skin
|
||||
function genSkinnedCategories(skin: string) {
|
||||
const result = new Map();
|
||||
for (const cat of CategoryNames) {
|
||||
const indices = [];
|
||||
const skinCat = (EmojiIndicesByCategoryAndSkin.get(skin) || new Map()).get(cat) || [];
|
||||
indices.push(...(EmojiIndicesByCategoryNoSkin.get(cat) || []));
|
||||
indices.push(...skinCat);
|
||||
|
||||
result.set(cat, indices);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
const getSkinnedCategories = memoize(genSkinnedCategories);
|
||||
export const EmojiIndicesByCategory = new Map([${skinnedCats.join(', ')}]);
|
||||
`;
|
||||
|
||||
// Create the emoji.ts file
|
||||
const webappUtilsEmojiTSDir = path.resolve(webappRootDir, 'channels', 'src', 'utils', 'emoji.ts');
|
||||
endResults.push(writeToFileAndPrint('emoji.ts', webappUtilsEmojiTSDir, emojiJSX));
|
||||
|
||||
const serverEmojiDataDir = path.resolve(serverRootDir, 'public', 'model', 'emoji_data.go');
|
||||
const emojiGo = `// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
// This file is automatically generated via \`/webapp/channels/build/make_emojis.mjs\`. Do not modify it manually.
|
||||
|
||||
package model
|
||||
|
||||
var SystemEmojis = map[string]string{
|
||||
${emojiImagesByAlias.join(`,
|
||||
`)},
|
||||
}
|
||||
`;
|
||||
|
||||
// Create the emoji_data.go file
|
||||
const goPromise = writeToFileAndPrint('emoji_data.go', serverEmojiDataDir, emojiGo);
|
||||
endResults.push(goPromise);
|
||||
|
||||
// Create individual emoji styles
|
||||
const cssCats = categoryNames.filter((cat) => cat !== 'custom').map((cat) => `.emoji-category-${cat} { background-image: url('${sheetFile}'); }`);
|
||||
const cssEmojis = [];
|
||||
for (const key of emojiFilePositions.keys()) {
|
||||
cssEmojis.push(`.emoji-${key} { background-position: ${emojiFilePositions.get(key)} }`);
|
||||
}
|
||||
|
||||
const cssRules = `.emojisprite-preview {
|
||||
width: ${EMOJI_SIZE_PADDED}px;
|
||||
max-width: none;
|
||||
height: ${EMOJI_SIZE_PADDED}px;
|
||||
background-repeat: no-repeat;
|
||||
cursor: pointer;
|
||||
-moz-transform: scale(0.5);
|
||||
transform: scale(0.5);
|
||||
transform-origin: 0 0;
|
||||
|
||||
@supports (zoom: 0.5) {
|
||||
-moz-transform: none;
|
||||
transform: none;
|
||||
zoom: 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
.emojisprite {
|
||||
width: ${EMOJI_SIZE_PADDED}px;
|
||||
max-width: none;
|
||||
height: ${EMOJI_SIZE_PADDED}px;
|
||||
background-repeat: no-repeat;
|
||||
border-radius: 18px;
|
||||
cursor: pointer;
|
||||
-moz-transform: scale(0.35);
|
||||
transform: scale(0.35);
|
||||
}
|
||||
|
||||
.emojisprite-loading {
|
||||
width: ${EMOJI_SIZE_PADDED}px;
|
||||
max-width: none;
|
||||
height: ${EMOJI_SIZE_PADDED}px;
|
||||
background-image: none !important;
|
||||
background-repeat: no-repeat;
|
||||
border-radius: 18px;
|
||||
cursor: pointer;
|
||||
-moz-transform: scale(0.35);
|
||||
transform: scale(0.35);
|
||||
}
|
||||
|
||||
@supports (zoom: 0.35) {
|
||||
.emojisprite,
|
||||
.emojisprite-loading {
|
||||
-moz-transform: none;
|
||||
transform: none;
|
||||
zoom: 0.35;
|
||||
}
|
||||
}
|
||||
|
||||
${cssCats.join('\n')}
|
||||
${cssEmojis.join('\n')}
|
||||
`;
|
||||
|
||||
// Create the emojisprite.scss file
|
||||
const emojispriteDir = path.resolve(webappRootDir, 'channels', 'src', 'sass', 'components', '_emojisprite.scss');
|
||||
endResults.push(writeToFileAndPrint('_emojisprite.scss', emojispriteDir, cssRules));
|
||||
|
||||
log('', '\n');
|
||||
log('info', 'Running "make-emojis" script...');
|
||||
Promise.all(endResults).then(() => {
|
||||
log('warn', 'Remember to npm run "i18n-extract" as categories might have changed.');
|
||||
log('warn', 'Remember to run "gofmt -w ./server/public/model/emoji_data.go" from the root of the repository.');
|
||||
log('success', 'make-emojis script completed successfully.');
|
||||
}).catch((err) => {
|
||||
control.abort(); // cancel any other file writing
|
||||
log('error', `There was an error while running make-emojis script: ${err}`);
|
||||
});
|
||||
35
webapp/channels/build/notice-file/README.md
Normal file
35
webapp/channels/build/notice-file/README.md
Normal file
@@ -0,0 +1,35 @@
|
||||
# Notice.txt File Configuration
|
||||
|
||||
We are automatically generating Notice.txt by using first-level dependencies of the project. The related pipeline uses `config.yaml` stored in this folder.
|
||||
|
||||
|
||||
## Configuration
|
||||
|
||||
Sample:
|
||||
|
||||
```
|
||||
title: "Mattermost Web App"
|
||||
copyright: "© 2017-present Mattermost, Inc. All Rights Reserved. See LICENSE.txt for license information."
|
||||
description: "This document includes a list of open source components used in Mattermost Web App, including those that have been modified."
|
||||
reviewers:
|
||||
- "mattermost/release-managers"
|
||||
- "mattermost/web-platform"
|
||||
search:
|
||||
- "package.json"
|
||||
- "packages/**/package.json"
|
||||
dependencies:
|
||||
- "wix"
|
||||
devDependencies:
|
||||
- "webpack"
|
||||
```
|
||||
|
||||
| Field | Type | Purpose |
|
||||
| :-- | :-- | :-- |
|
||||
| title | string | Field content will be used as a title of the application. See first line of `NOTICE.txt` file. |
|
||||
| copyright | string | Field content will be used as a copyright message. See second line of `NOTICE.txt` file. |
|
||||
| description | string | Field content will be used as notice file description. See third line of `NOTICE.txt` file. |
|
||||
| reviewers | array of GitHub user/teams | Those will be automatically assigned to the PRs as reviewers. |
|
||||
| dependencies | array | If any dependency name mentioned, it will be automatically added even if it is not a first-level dependency. |
|
||||
| devDependencies | array | If any dependency name mentioned, it will be added when it is referenced in devDependency section. |
|
||||
| search | array | Pipeline will search for package.json files located. Globstar format is supported `packages/**/package.json`. |
|
||||
|
||||
16
webapp/channels/build/notice-file/config.yaml
Normal file
16
webapp/channels/build/notice-file/config.yaml
Normal file
@@ -0,0 +1,16 @@
|
||||
---
|
||||
|
||||
title: "Mattermost Web App"
|
||||
copyright: "© 2017-present Mattermost, Inc. All Rights Reserved. See LICENSE.txt for license information."
|
||||
description: "This document includes a list of open source components used in Mattermost Web App, including those that have been modified."
|
||||
reviewers:
|
||||
- "mattermost/release-managers"
|
||||
- "mattermost/web-platform"
|
||||
search:
|
||||
- "package.json"
|
||||
- "packages/**/package.json"
|
||||
dependencies: []
|
||||
devDependencies:
|
||||
- "webpack"
|
||||
|
||||
...
|
||||
Reference in New Issue
Block a user