1 | import { join, resolve, basename } from 'path';
|
2 | import {
|
3 | mkdirp,
|
4 | copy,
|
5 | remove,
|
6 | writeFile,
|
7 | symlink,
|
8 | } from 'fs-extra';
|
9 | import { uniq } from 'lodash';
|
10 |
|
11 | import * as cssBuilders from './css-builders';
|
12 | import { clearCache } from './parse';
|
13 | import { getCustomizations } from './customizations';
|
14 |
|
15 | const nconf = require.main.require('nconf');
|
16 | const winston = require.main.require('winston');
|
17 | const plugins = require.main.require('./src/plugins');
|
18 |
|
19 | export const assetsDir = join(__dirname, '../emoji');
|
20 |
|
21 | const linkDirs = (sourceDir: string, destDir: string) => {
|
22 | const type = (process.platform === 'win32') ? 'junction' : 'dir';
|
23 | return symlink(sourceDir, destDir, type);
|
24 | };
|
25 |
|
26 | export const tableFile = join(assetsDir, 'table.json');
|
27 | export const aliasesFile = join(assetsDir, 'aliases.json');
|
28 | export const asciiFile = join(assetsDir, 'ascii.json');
|
29 | export const charactersFile = join(assetsDir, 'characters.json');
|
30 | export const categoriesFile = join(assetsDir, 'categories.json');
|
31 | export const packsFile = join(assetsDir, 'packs.json');
|
32 |
|
33 | export default async function build() {
|
34 | winston.verbose('[emoji] Building emoji assets');
|
35 |
|
36 |
|
37 | const { packs }: { packs: EmojiDefinition[] } = await plugins.fireHook('filter:emoji.packs', { packs: [] });
|
38 |
|
39 | const filtered = packs.filter((pack) => {
|
40 | if (pack && pack.id && pack.name && pack.mode && pack.dictionary && pack.path) {
|
41 | return true;
|
42 | }
|
43 |
|
44 | winston.warn('[emoji] pack invalid: ', pack.path || pack.id);
|
45 | return false;
|
46 | });
|
47 |
|
48 | winston.verbose('[emoji] Loaded packs: ' + filtered.map((pack) => pack.id).join(', '));
|
49 |
|
50 | await remove(assetsDir);
|
51 | await mkdirp(assetsDir);
|
52 |
|
53 | const customizations = await getCustomizations();
|
54 |
|
55 | const table: MetaData.Table = {};
|
56 | const aliases: MetaData.Aliases = {};
|
57 | const ascii: MetaData.Ascii = {};
|
58 | const characters: MetaData.Characters = {};
|
59 |
|
60 | const categoriesInfo: MetaData.Categories = {};
|
61 | const packsInfo: MetaData.Packs = [];
|
62 |
|
63 | packs.forEach((pack) => {
|
64 | packsInfo.push({
|
65 | name: pack.name,
|
66 | id: pack.id,
|
67 | attribution: pack.attribution,
|
68 | license: pack.license,
|
69 | });
|
70 |
|
71 | Object.keys(pack.dictionary).forEach((key) => {
|
72 | const name = key.toLowerCase();
|
73 | const emoji = pack.dictionary[key];
|
74 |
|
75 | if (!table[name]) {
|
76 | table[name] = {
|
77 | name,
|
78 | character: emoji.character || `:${name}:`,
|
79 | image: emoji.image || '',
|
80 | pack: pack.id,
|
81 | aliases: emoji.aliases || [],
|
82 | keywords: emoji.keywords || [],
|
83 | };
|
84 | }
|
85 |
|
86 | if (!characters[emoji.character]) {
|
87 | characters[emoji.character] = name;
|
88 | }
|
89 |
|
90 | if (emoji.aliases) {
|
91 | emoji.aliases.forEach((alias) => {
|
92 | const a = alias.toLowerCase();
|
93 | if (!aliases[a]) {
|
94 | aliases[a] = name;
|
95 | }
|
96 | });
|
97 | }
|
98 |
|
99 | if (emoji.ascii) {
|
100 | emoji.ascii.forEach((str) => {
|
101 | if (!ascii[str]) {
|
102 | ascii[str] = name;
|
103 | }
|
104 | });
|
105 | }
|
106 |
|
107 | const categories = emoji.categories || ['other'];
|
108 | categories.forEach((category) => {
|
109 | categoriesInfo[category] = categoriesInfo[category] || [];
|
110 | categoriesInfo[category].push(name);
|
111 | });
|
112 | });
|
113 | });
|
114 |
|
115 | Object.keys(categoriesInfo).forEach((category) => {
|
116 | categoriesInfo[category] = uniq(categoriesInfo[category]);
|
117 | });
|
118 |
|
119 | customizations.emojis.forEach((emoji) => {
|
120 | const name = emoji.name.toLowerCase();
|
121 |
|
122 | table[name] = {
|
123 | name,
|
124 | character: `:${name}:`,
|
125 | pack: 'customizations',
|
126 | keywords: [],
|
127 | image: emoji.image,
|
128 | aliases: emoji.aliases,
|
129 | };
|
130 |
|
131 | emoji.aliases.forEach((alias) => {
|
132 | const a = alias.toLowerCase();
|
133 | if (!aliases[a]) {
|
134 | aliases[a] = name;
|
135 | }
|
136 | });
|
137 |
|
138 | emoji.ascii.forEach((str) => {
|
139 | if (!ascii[str]) {
|
140 | ascii[str] = name;
|
141 | }
|
142 | });
|
143 |
|
144 | categoriesInfo.custom = categoriesInfo.custom || [];
|
145 | categoriesInfo.custom.push(name);
|
146 | });
|
147 | customizations.adjuncts.forEach((adjunct) => {
|
148 | const name = adjunct.name;
|
149 | if (!table[name]) { return; }
|
150 |
|
151 | table[name] = {
|
152 | ...table[name],
|
153 | aliases: table[name].aliases.concat(adjunct.aliases),
|
154 | };
|
155 |
|
156 | adjunct.aliases.forEach((alias) => { aliases[alias] = name; });
|
157 | adjunct.ascii.forEach((str) => { ascii[str] = name; });
|
158 | });
|
159 |
|
160 |
|
161 | const css = packs.map((pack) => cssBuilders[pack.mode](pack)).join('\n');
|
162 | const cssFile = `${css}\n.emoji-customizations {
|
163 | display: inline-block;
|
164 | height: 23px;
|
165 | margin-top: -1px;
|
166 | margin-bottom: -1px;
|
167 | }`.split('\n').map((x) => x.trim()).join('');
|
168 |
|
169 |
|
170 | const assetOperations = packs.map(async (pack) => {
|
171 | const dir = join(assetsDir, pack.id);
|
172 |
|
173 | if (pack.mode === 'images') {
|
174 | await linkDirs(resolve(pack.path, pack.images.directory), dir);
|
175 | } else if (pack.mode === 'sprite') {
|
176 | const filename = basename(pack.sprite.file);
|
177 | await mkdirp(dir);
|
178 | await copy(resolve(pack.path, pack.sprite.file), join(dir, filename));
|
179 | } else {
|
180 | const fontFiles = [
|
181 | pack.font.eot,
|
182 | pack.font.svg,
|
183 | pack.font.woff,
|
184 | pack.font.ttf,
|
185 | pack.font.woff2,
|
186 | ].filter(Boolean);
|
187 |
|
188 | await mkdirp(dir);
|
189 | await Promise.all(fontFiles.map(async (file) => {
|
190 | const filename = basename(file);
|
191 | copy(resolve(pack.path, file), join(dir, filename));
|
192 | }));
|
193 | }
|
194 | });
|
195 |
|
196 | await Promise.all([
|
197 | ...assetOperations,
|
198 |
|
199 | writeFile(join(assetsDir, 'styles.css'), cssFile, { encoding: 'utf8' }),
|
200 |
|
201 | writeFile(tableFile, JSON.stringify(table)),
|
202 | writeFile(aliasesFile, JSON.stringify(aliases)),
|
203 | writeFile(asciiFile, JSON.stringify(ascii)),
|
204 | writeFile(charactersFile, JSON.stringify(characters)),
|
205 | writeFile(categoriesFile, JSON.stringify(categoriesInfo)),
|
206 | writeFile(packsFile, JSON.stringify(packsInfo)),
|
207 |
|
208 | linkDirs(
|
209 | join(nconf.get('upload_path'), 'emoji'),
|
210 | join(assetsDir, 'customizations')
|
211 | ),
|
212 | ]);
|
213 |
|
214 | clearCache();
|
215 | }
|