@pine-ds/icons 2.0.2 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cheatsheet.html +20 -4
- package/dist/collection/components/pds-icon/pds-icon.js.map +1 -1
- package/dist/collection/components/pds-icon/request.js.map +1 -1
- package/dist/collection/components/pds-icon/svg/blog-filled.svg +1 -0
- package/dist/collection/components/pds-icon/svg/flash-filled.svg +1 -0
- package/dist/collection/components/pds-icon/svg/flash.svg +1 -0
- package/dist/collection/components/pds-icon/svg/form-filled.svg +1 -0
- package/dist/collection/components/pds-icon/svg/mail-filled.svg +1 -0
- package/dist/collection/components/pds-icon/svg/map.svg +1 -0
- package/dist/collection/components/pds-icon/svg/publish.svg +1 -0
- package/dist/collection/components/pds-icon/svg/wrench.svg +1 -0
- package/dist/collection/components/pds-icon/test/pds-icon.e2e.js.map +1 -1
- package/dist/collection/components/pds-icon/test/pds-icon.spec.js.map +1 -1
- package/dist/collection/components/pds-icon/utils.js.map +1 -1
- package/dist/collection/components/pds-icon/validate.js.map +1 -1
- package/dist/collection/index.js.map +1 -1
- package/dist/docs.json +1 -1
- package/dist/pds-icons.json +61 -1
- package/dist/pds-icons.symbols.svg +9 -1
- package/dist/svg/blog-filled.svg +1 -0
- package/dist/svg/flash-filled.svg +1 -0
- package/dist/svg/flash.svg +1 -0
- package/dist/svg/form-filled.svg +1 -0
- package/dist/svg/mail-filled.svg +1 -0
- package/dist/svg/map.svg +1 -0
- package/dist/svg/publish.svg +1 -0
- package/dist/svg/wrench.svg +1 -0
- package/icons/index.d.ts +9 -1
- package/icons/index.js +9 -1
- package/icons/index.mjs +9 -1
- package/icons/package.json +1 -1
- package/package.json +1 -1
- package/dist/scripts/collection-copy.js +0 -28
- package/dist/scripts/collection-copy.js.map +0 -1
- package/dist/scripts/figma_icons/figma-icon-export.js +0 -666
- package/dist/scripts/figma_icons/figma-icon-export.js.map +0 -1
- package/dist/scripts/figma_icons/types.js +0 -2
- package/dist/scripts/figma_icons/types.js.map +0 -1
- package/dist/scripts/helpers.js +0 -51
- package/dist/scripts/helpers.js.map +0 -1
- package/dist/scripts/optimize-svgs.js +0 -352
- package/dist/scripts/optimize-svgs.js.map +0 -1
- package/dist/types/Users/julian.skinner/kajabi/pine-icons/.stencil/scripts/collection-copy.d.ts +0 -1
- package/dist/types/Users/julian.skinner/kajabi/pine-icons/.stencil/scripts/figma_icons/figma-icon-export.d.ts +0 -1
- package/dist/types/Users/julian.skinner/kajabi/pine-icons/.stencil/scripts/figma_icons/types.d.ts +0 -112
- package/dist/types/Users/julian.skinner/kajabi/pine-icons/.stencil/scripts/helpers.d.ts +0 -55
- package/dist/types/Users/julian.skinner/kajabi/pine-icons/.stencil/scripts/optimize-svgs.d.ts +0 -7
|
@@ -1,666 +0,0 @@
|
|
|
1
|
-
import * as dotenv from "dotenv";
|
|
2
|
-
import { run as optimizeSvgs } from "../optimize-svgs";
|
|
3
|
-
import { collectionCopy } from "../collection-copy";
|
|
4
|
-
/* eslint-disable @typescript-eslint/no-var-requires */
|
|
5
|
-
const axios = require('axios');
|
|
6
|
-
import chalk from "chalk"; // Terminal string styling done right
|
|
7
|
-
import path from "path";
|
|
8
|
-
import fs from "fs-extra";
|
|
9
|
-
import mkdirp from "mkdirp";
|
|
10
|
-
import cliui from "cliui";
|
|
11
|
-
import { simpleGit } from "simple-git";
|
|
12
|
-
if (process.env.NODE_ENV !== 'prod') {
|
|
13
|
-
dotenv.config({ path: `${process.cwd()}/.env` });
|
|
14
|
-
}
|
|
15
|
-
const info = chalk.white;
|
|
16
|
-
const error = chalk.red.bold;
|
|
17
|
-
const detail = chalk.yellowBright;
|
|
18
|
-
const log = console.log;
|
|
19
|
-
const baseDir = process.cwd();
|
|
20
|
-
const scriptsDir = path.join(baseDir, 'scripts');
|
|
21
|
-
const srcDir = path.join(baseDir, 'src');
|
|
22
|
-
const srcSvgBasePath = path.join(srcDir, 'svg');
|
|
23
|
-
const date = new Date();
|
|
24
|
-
const strDate = [date.getFullYear().toString(), (date.getMonth() + 1).toString().padStart(2, '0'), date.getDate().toString().padStart(2, '0')].join('-');
|
|
25
|
-
let figmaClient;
|
|
26
|
-
const run = async (rootDir) => {
|
|
27
|
-
try {
|
|
28
|
-
const config = await loadFigmaIconConfig(rootDir);
|
|
29
|
-
figmaClient = client(config.figmaAccessToken);
|
|
30
|
-
const data = await processData(rootDir, config);
|
|
31
|
-
await optimizeSvgs(rootDir, true);
|
|
32
|
-
const git = gitClient();
|
|
33
|
-
await git.add(srcSvgBasePath);
|
|
34
|
-
const statusResults = await git.status([srcSvgBasePath]);
|
|
35
|
-
const filesChanged = statusResults.files;
|
|
36
|
-
if (filesChanged.length <= 0) {
|
|
37
|
-
log(detail('No changes were found. Exiting the process!!!!'));
|
|
38
|
-
removeTmpDirectory(config);
|
|
39
|
-
return;
|
|
40
|
-
}
|
|
41
|
-
log('Copying collections...');
|
|
42
|
-
await collectionCopy(rootDir);
|
|
43
|
-
log(`${makeResultsTable(data.downloaded)}\n`);
|
|
44
|
-
console.log('Icon Count: ', data.icons.length, 'Result Count: ', data.downloaded.length);
|
|
45
|
-
createJsonIconList(data.icons, srcDir);
|
|
46
|
-
await createChangelogHTML(statusResults);
|
|
47
|
-
removeTmpDirectory(config);
|
|
48
|
-
// restore staged files in case of failure
|
|
49
|
-
const { exec } = require('node:child_process');
|
|
50
|
-
exec(`git restore --staged ${srcSvgBasePath}`);
|
|
51
|
-
}
|
|
52
|
-
catch (e) {
|
|
53
|
-
log(error(e));
|
|
54
|
-
process.exit(1);
|
|
55
|
-
}
|
|
56
|
-
};
|
|
57
|
-
/**
|
|
58
|
-
* Reads the file contents to read the Svg File and stores
|
|
59
|
-
* into a property to be used later
|
|
60
|
-
*
|
|
61
|
-
* @param status - staus indicator, this could be D - deleted, M - modified, or empty - new
|
|
62
|
-
* @param filePath - relattive path to the file
|
|
63
|
-
* @returns - SvgDiffResult
|
|
64
|
-
*/
|
|
65
|
-
const buildBeforeAndAfterSvg = async (status, filePath, previousFilePath = null) => {
|
|
66
|
-
const filename = path.basename(filePath);
|
|
67
|
-
const previousFileName = previousFilePath && path.basename(previousFilePath);
|
|
68
|
-
let beforeSvg = null;
|
|
69
|
-
let afterSvg = null;
|
|
70
|
-
switch (status) {
|
|
71
|
-
case 'D':
|
|
72
|
-
beforeSvg = await getFileContentsFromGit(filePath);
|
|
73
|
-
break;
|
|
74
|
-
case 'M':
|
|
75
|
-
beforeSvg = await getFileContentsFromGit(filePath);
|
|
76
|
-
afterSvg = await getFileContentsFromDisk(filename);
|
|
77
|
-
break;
|
|
78
|
-
case 'R':
|
|
79
|
-
beforeSvg = await getFileContentsFromGit(previousFilePath);
|
|
80
|
-
afterSvg = await getFileContentsFromDisk(filename);
|
|
81
|
-
break;
|
|
82
|
-
case '':
|
|
83
|
-
afterSvg = await getFileContentsFromDisk(filename);
|
|
84
|
-
break;
|
|
85
|
-
}
|
|
86
|
-
return {
|
|
87
|
-
previousFileName,
|
|
88
|
-
filename,
|
|
89
|
-
status,
|
|
90
|
-
before: beforeSvg,
|
|
91
|
-
after: afterSvg,
|
|
92
|
-
};
|
|
93
|
-
};
|
|
94
|
-
/**
|
|
95
|
-
* Generates a Header and table
|
|
96
|
-
*
|
|
97
|
-
* @param sectionName - name used for the Header
|
|
98
|
-
* @param data - an array of {@link SVGDiffResult}
|
|
99
|
-
* @returns The string of html used to represent a section e.g Added in the Changelog
|
|
100
|
-
*/
|
|
101
|
-
const buildHTMLSection = (sectionName, data) => {
|
|
102
|
-
const content = `<h2>${sectionName}</h2>`;
|
|
103
|
-
const table = buildHTMLTable(data, sectionName == 'Renamed');
|
|
104
|
-
return [content, table].join('\n');
|
|
105
|
-
};
|
|
106
|
-
/**
|
|
107
|
-
* Generates a HTML Table
|
|
108
|
-
*
|
|
109
|
-
* @param data an array of {@link SvgDiffResult}
|
|
110
|
-
* @returns - The html table markup
|
|
111
|
-
*/
|
|
112
|
-
const buildHTMLTable = (data, isRenamed = false) => {
|
|
113
|
-
const tableRows = data.map((diff) => `<tr>
|
|
114
|
-
${isRenamed ? `<td>${diff.previousFileName}</td>` : ''}
|
|
115
|
-
<td>${diff.filename}</td>
|
|
116
|
-
<td>${diff.before || ''}</td>
|
|
117
|
-
<td>${diff.after || ''}</td>
|
|
118
|
-
</tr>`);
|
|
119
|
-
const tableBody = `<tbody>
|
|
120
|
-
${tableRows.join('')}
|
|
121
|
-
</tbody>`;
|
|
122
|
-
const table = `<table>
|
|
123
|
-
<thead>
|
|
124
|
-
<tr>
|
|
125
|
-
${isRenamed ? `<td>Previous Filename</td>` : ''}
|
|
126
|
-
<td>${isRenamed ? `New Filename</td>` : 'FileName'}</td>
|
|
127
|
-
<td>Before</td>
|
|
128
|
-
<td>After</td>
|
|
129
|
-
</tr>
|
|
130
|
-
</thead>
|
|
131
|
-
${tableBody}
|
|
132
|
-
</table>`;
|
|
133
|
-
return table;
|
|
134
|
-
};
|
|
135
|
-
/**
|
|
136
|
-
* Creates the axios client with the appropriate
|
|
137
|
-
* headers and url.
|
|
138
|
-
*
|
|
139
|
-
* @param apiToken required token to pass in the headers
|
|
140
|
-
* @returns Axios client object
|
|
141
|
-
*/
|
|
142
|
-
const client = (apiToken) => {
|
|
143
|
-
const figmaBaseApiURL = 'https://api.figma.com/v1';
|
|
144
|
-
const instance = axios.create({
|
|
145
|
-
baseURL: figmaBaseApiURL,
|
|
146
|
-
headers: {
|
|
147
|
-
'Content-Type': 'application/json',
|
|
148
|
-
'X-Figma-Token': apiToken
|
|
149
|
-
}
|
|
150
|
-
});
|
|
151
|
-
instance.interceptors.request.use((conf) => {
|
|
152
|
-
conf.startTime = new Date().getTime();
|
|
153
|
-
return conf;
|
|
154
|
-
});
|
|
155
|
-
return instance;
|
|
156
|
-
};
|
|
157
|
-
/**
|
|
158
|
-
* Creates the Changelog.html file based on the
|
|
159
|
-
* latest data pulled from Figma
|
|
160
|
-
*
|
|
161
|
-
* @returns The results from SimpleGit.status()
|
|
162
|
-
*/
|
|
163
|
-
const createChangelogHTML = async (statusResults) => {
|
|
164
|
-
const { modified, created, deleted, renamed } = await processStatusResults(statusResults);
|
|
165
|
-
// Adding or Deleting will be Major version bump
|
|
166
|
-
// Modifying will be a MINOR version bump
|
|
167
|
-
const html = fs.readFileSync(path.join(scriptsDir, 'figma_icons', 'changelog-template.html'), 'utf8')
|
|
168
|
-
.replace(/{{date}}/g, strDate)
|
|
169
|
-
.replace(/{{modified}}/g, statusResults.modified.length.toString())
|
|
170
|
-
.replace(/{{deleted}}/g, statusResults.deleted.length.toString())
|
|
171
|
-
.replace(/{{created}}/g, statusResults.created.length.toString())
|
|
172
|
-
.replace(/{{renamed}}/g, statusResults.renamed.length.toString())
|
|
173
|
-
.replace(/{{content}}/g, [created, modified, deleted, renamed].join('\n'));
|
|
174
|
-
const changelogFilename = `${strDate}-changelog.html`;
|
|
175
|
-
const changelogPath = path.join(baseDir, 'changelogs');
|
|
176
|
-
const fullChangelogFilename = path.join(changelogPath, changelogFilename);
|
|
177
|
-
// Write file to changelogs directory
|
|
178
|
-
fs.writeFileSync(fullChangelogFilename, html);
|
|
179
|
-
const arrChangelogs = fs.readdirSync(changelogPath);
|
|
180
|
-
const changelogRecords = [];
|
|
181
|
-
let numberOfChangelogs = 0;
|
|
182
|
-
arrChangelogs.reverse().forEach((filename, idx) => {
|
|
183
|
-
if (path.extname(filename) === '.html') {
|
|
184
|
-
if (idx < 10) {
|
|
185
|
-
changelogRecords.push(`<a href="changelogs/${filename}">${path.basename(filename)}</a>`);
|
|
186
|
-
}
|
|
187
|
-
numberOfChangelogs++;
|
|
188
|
-
}
|
|
189
|
-
});
|
|
190
|
-
log('Number of Changelog files found: ', detail(numberOfChangelogs));
|
|
191
|
-
const indexHtml = fs.readFileSync(path.join(baseDir, 'src', 'index-template.html'), 'utf8')
|
|
192
|
-
.replace(/{{changelogs}}/g, changelogRecords.join(' <br/>'));
|
|
193
|
-
// Copy index.html file to www worker folder
|
|
194
|
-
fs.writeFileSync(path.join(baseDir, 'src', 'index.html'), indexHtml);
|
|
195
|
-
if (fs.ensureDir(path.join(baseDir, 'www'))) {
|
|
196
|
-
const wwwChangelogPath = path.join(baseDir, 'www', 'changelogs');
|
|
197
|
-
const wwwChangelogFile = path.join(wwwChangelogPath, changelogFilename);
|
|
198
|
-
// Create Changelogs folder in `www` worker folder
|
|
199
|
-
fs.mkdirSync(wwwChangelogPath, { recursive: true });
|
|
200
|
-
fs.copyFileSync(fullChangelogFilename, wwwChangelogFile);
|
|
201
|
-
}
|
|
202
|
-
return statusResults;
|
|
203
|
-
};
|
|
204
|
-
/**
|
|
205
|
-
* Creates JSON data file that contains additional
|
|
206
|
-
* metadata
|
|
207
|
-
*
|
|
208
|
-
* @example
|
|
209
|
-
* ```
|
|
210
|
-
* {
|
|
211
|
-
* "category": "features",
|
|
212
|
-
* "name": "access-key",
|
|
213
|
-
* "tags": [
|
|
214
|
-
* "access",
|
|
215
|
-
* "key",
|
|
216
|
-
* "license",
|
|
217
|
-
* "object",
|
|
218
|
-
* "password",
|
|
219
|
-
* "secure"
|
|
220
|
-
* ]
|
|
221
|
-
* }
|
|
222
|
-
* ```
|
|
223
|
-
*
|
|
224
|
-
* @param icons - array of FigmaIcons
|
|
225
|
-
* @param outputDir - output directory to save the JSON data
|
|
226
|
-
*/
|
|
227
|
-
const createJsonIconList = (icons, outputDir) => {
|
|
228
|
-
try {
|
|
229
|
-
icons = icons.sort((a, b) => {
|
|
230
|
-
if (a.name < b.name)
|
|
231
|
-
return -1;
|
|
232
|
-
if (a.name > b.name)
|
|
233
|
-
return 1;
|
|
234
|
-
return 0;
|
|
235
|
-
});
|
|
236
|
-
const outputObj = {
|
|
237
|
-
icons: icons.map((icon) => {
|
|
238
|
-
var _a;
|
|
239
|
-
let tags;
|
|
240
|
-
if (icon.tags) {
|
|
241
|
-
tags = (_a = icon.tags) === null || _a === void 0 ? void 0 : _a.split(',').map((tag) => (tag.trim())).sort();
|
|
242
|
-
}
|
|
243
|
-
else {
|
|
244
|
-
tags = icon.name.split('-');
|
|
245
|
-
}
|
|
246
|
-
return {
|
|
247
|
-
name: icon.name,
|
|
248
|
-
category: icon.frame || null,
|
|
249
|
-
tags: tags.sort(),
|
|
250
|
-
};
|
|
251
|
-
})
|
|
252
|
-
};
|
|
253
|
-
const srcJsonStr = JSON.stringify(outputObj, null, 2) + '\n';
|
|
254
|
-
fs.writeFileSync(path.join(outputDir, 'icon-data.json'), srcJsonStr);
|
|
255
|
-
}
|
|
256
|
-
catch (e) {
|
|
257
|
-
logErrorMessage('createJsonIconList', e);
|
|
258
|
-
}
|
|
259
|
-
};
|
|
260
|
-
/**
|
|
261
|
-
* Creates the directory that will
|
|
262
|
-
* contain the SVGs
|
|
263
|
-
*
|
|
264
|
-
* @param outputDir - The directory name to create
|
|
265
|
-
*/
|
|
266
|
-
const createOutputDirectory = async (outputDir) => {
|
|
267
|
-
return new Promise((resolve) => {
|
|
268
|
-
const directory = path.resolve(outputDir);
|
|
269
|
-
if (!fs.existsSync(directory)) {
|
|
270
|
-
log(info(`Directory ${outputDir} does not exist`));
|
|
271
|
-
if (mkdirp.sync(directory)) {
|
|
272
|
-
log(info(`Created directory ${outputDir}`));
|
|
273
|
-
resolve();
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
else {
|
|
277
|
-
resolve();
|
|
278
|
-
}
|
|
279
|
-
});
|
|
280
|
-
};
|
|
281
|
-
/**
|
|
282
|
-
* Downloads the images
|
|
283
|
-
*
|
|
284
|
-
* @param icon - The FigmaIcon object
|
|
285
|
-
* @param outputDir - The directory that the svg will be downloaded
|
|
286
|
-
* @returns a object with the name and size of the svg
|
|
287
|
-
*/
|
|
288
|
-
const downloadImage = (icon, outputDir) => {
|
|
289
|
-
const nameClean = icon.name.toLowerCase();
|
|
290
|
-
;
|
|
291
|
-
const directory = outputDir;
|
|
292
|
-
const imagePath = path.resolve(directory, `${nameClean}.svg`);
|
|
293
|
-
const writer = fs.createWriteStream(imagePath);
|
|
294
|
-
// log('Image url: ', info(icon.url), 'Frame: ', info(icon.frame));
|
|
295
|
-
// log('Image Path: ', info(imagePath));
|
|
296
|
-
axios.get(icon.url, { responseType: 'stream' })
|
|
297
|
-
.then((res) => {
|
|
298
|
-
res.data.pipe(writer);
|
|
299
|
-
})
|
|
300
|
-
.catch((err) => {
|
|
301
|
-
if (err.message === 'Socket connection timeout') {
|
|
302
|
-
log(detail('Create new Figma access Token'));
|
|
303
|
-
}
|
|
304
|
-
log('Icon name: ', detail(icon.name));
|
|
305
|
-
log('Error details ', '\nMessage: ', error(err.message), '\nUrl: ', detail(err.config.url));
|
|
306
|
-
log(chalk.red.bold('Something went wrong fetching the image from S3, please try again'));
|
|
307
|
-
log(chalk.red.bold(err));
|
|
308
|
-
});
|
|
309
|
-
return new Promise((resolve, reject) => {
|
|
310
|
-
writer.on('finish', () => {
|
|
311
|
-
// log(info(`Saved ${name}.svg`, fs.statSync(imagePath).size))
|
|
312
|
-
icon.filesize = fs.statSync(imagePath).size;
|
|
313
|
-
resolve({
|
|
314
|
-
name: `${icon.name}.svg`,
|
|
315
|
-
size: fs.statSync(imagePath).size
|
|
316
|
-
});
|
|
317
|
-
});
|
|
318
|
-
writer.on('error', (err) => {
|
|
319
|
-
console.log('error writting file', err);
|
|
320
|
-
reject(err);
|
|
321
|
-
});
|
|
322
|
-
});
|
|
323
|
-
};
|
|
324
|
-
/**
|
|
325
|
-
* Extract all the icons from figma page data.
|
|
326
|
-
*
|
|
327
|
-
* @param pageData - an object containing the Page details
|
|
328
|
-
* @param ignoreFrames - an array of names to be ignored
|
|
329
|
-
* @param componentMetadata - an object containing additional details for the icon
|
|
330
|
-
* @returns An array of FigmaIcons
|
|
331
|
-
*/
|
|
332
|
-
const extractIcons = (pageData, ignoreFrames, componentMetadata) => {
|
|
333
|
-
const iconFrames = pageData.children;
|
|
334
|
-
const iconLibrary = [];
|
|
335
|
-
iconFrames.forEach((frame) => {
|
|
336
|
-
if (['COMPONENT_SET', 'FRAME'].includes(frame.type) && (!frame.name.startsWith('_') && !(ignoreFrames === null || ignoreFrames === void 0 ? void 0 : ignoreFrames.includes(frame.name)))) {
|
|
337
|
-
const components = frame.children;
|
|
338
|
-
components.forEach((component) => {
|
|
339
|
-
// if ( componentMetadata[component.id] === undefined) {
|
|
340
|
-
// console.log('Frame: ', frame.name, 'Component Id: ', component.id, 'Metadata: ', componentMetadata[component.id])
|
|
341
|
-
// }
|
|
342
|
-
const icon = {
|
|
343
|
-
id: component.id,
|
|
344
|
-
frame: frame.name.toLowerCase().replaceAll(' ', '-'),
|
|
345
|
-
name: !isNaN(component.name) ? `number-${component.name}` : component.name
|
|
346
|
-
};
|
|
347
|
-
if (componentMetadata[component.id] !== undefined) {
|
|
348
|
-
icon["tags"] = componentMetadata[component.id].description;
|
|
349
|
-
}
|
|
350
|
-
iconLibrary.push(icon);
|
|
351
|
-
});
|
|
352
|
-
}
|
|
353
|
-
});
|
|
354
|
-
return iconLibrary;
|
|
355
|
-
};
|
|
356
|
-
/**
|
|
357
|
-
* Process that finds and downloads SVGs
|
|
358
|
-
*
|
|
359
|
-
* @param page - Page object in figma
|
|
360
|
-
* @param fileId - The unique Id for the Figma File
|
|
361
|
-
*/
|
|
362
|
-
const fetchAndDownloadIcons = async (page, fileId, config, componentMetadata) => {
|
|
363
|
-
try {
|
|
364
|
-
const iconLibrary = extractIcons(page, config.ignoreFrames, componentMetadata);
|
|
365
|
-
log(chalk.yellowBright(iconLibrary.length), info('icons have been extracted'));
|
|
366
|
-
const icons = await fetchImageUrls(fileId, iconLibrary);
|
|
367
|
-
await createOutputDirectory(config.downloadPath);
|
|
368
|
-
fs.emptyDirSync(config.downloadPath);
|
|
369
|
-
const allIcons = icons.map((icon) => downloadImage(icon, config.downloadPath));
|
|
370
|
-
const results = await Promise.all(allIcons).then((res) => { return res; });
|
|
371
|
-
return {
|
|
372
|
-
icons: iconLibrary,
|
|
373
|
-
downloaded: results,
|
|
374
|
-
};
|
|
375
|
-
}
|
|
376
|
-
catch (e) {
|
|
377
|
-
logErrorMessage('fetchAndDonwloadIcons', e);
|
|
378
|
-
}
|
|
379
|
-
};
|
|
380
|
-
/**
|
|
381
|
-
* Process that will make an API call to retrieve
|
|
382
|
-
* the FigmaFile data
|
|
383
|
-
*
|
|
384
|
-
* @oaram fileId - string: the fileId of the Figma File / Branch
|
|
385
|
-
* @returns - JSON data from Figma API - See {@link https://www.figma.com/developers/api#get-files-endpoint | GET File}
|
|
386
|
-
*/
|
|
387
|
-
const fetchFigmaData = (fileId) => {
|
|
388
|
-
const requestPath = `files/${fileId}?branch_data=true`;
|
|
389
|
-
const data = figmaClient.get(requestPath)
|
|
390
|
-
.then((resp) => {
|
|
391
|
-
return resp.data;
|
|
392
|
-
})
|
|
393
|
-
.catch((err) => {
|
|
394
|
-
log(error('Error occurred fetching Figma Data, error: ', err));
|
|
395
|
-
});
|
|
396
|
-
return data;
|
|
397
|
-
};
|
|
398
|
-
/**
|
|
399
|
-
* Sends a request to get a collection
|
|
400
|
-
* icon urls to download
|
|
401
|
-
*
|
|
402
|
-
* @param fileId - The FileId that contains the icons
|
|
403
|
-
* @param icons - An array of @see {@link FigmaIcon}
|
|
404
|
-
* @returns - Array<FigmaIcon> with urls
|
|
405
|
-
*/
|
|
406
|
-
const fetchImageUrls = (fileId, icons) => {
|
|
407
|
-
return new Promise((resolve) => {
|
|
408
|
-
const iconIds = icons.map(icon => icon.id).join(',');
|
|
409
|
-
figmaClient.get(`images/${fileId}?ids=${iconIds}&format=svg`)
|
|
410
|
-
.then((res) => {
|
|
411
|
-
const imageUrls = res.data.images;
|
|
412
|
-
log(info(`Image Api returned ${chalk.yellowBright(Object.keys(res.data.images).length)} image urls\n`));
|
|
413
|
-
icons.forEach(icon => {
|
|
414
|
-
icon.url = imageUrls[icon.id];
|
|
415
|
-
});
|
|
416
|
-
resolve(icons);
|
|
417
|
-
})
|
|
418
|
-
.catch((err) => {
|
|
419
|
-
log(error('Unable to get icons: ', err));
|
|
420
|
-
process.exit(1);
|
|
421
|
-
});
|
|
422
|
-
});
|
|
423
|
-
};
|
|
424
|
-
/**
|
|
425
|
-
* Locate the page in the Figma Data
|
|
426
|
-
*
|
|
427
|
-
* @param document - Figma document data
|
|
428
|
-
* @param pageName - Name of the page to find
|
|
429
|
-
* @returns a Node with the Page data
|
|
430
|
-
*/
|
|
431
|
-
const findPage = (document, pageName) => {
|
|
432
|
-
const iconPage = document.children.find(c => c.name === pageName);
|
|
433
|
-
if (!iconPage) {
|
|
434
|
-
log(error('No Page found, please check the name "', chalk.white.bgRedBright(pageName), '"'));
|
|
435
|
-
process.exit(1);
|
|
436
|
-
// throw error(`No Page found, please check the name "${chalk.white.bgRedBright(pageName)}"`)
|
|
437
|
-
}
|
|
438
|
-
return iconPage;
|
|
439
|
-
};
|
|
440
|
-
/**
|
|
441
|
-
* Reads the file contents using git cat-file
|
|
442
|
-
* See {@link https://git-scm.com/docs/git-cat-file} for more details
|
|
443
|
-
*
|
|
444
|
-
* @param filePath - the relative path to the file on disk
|
|
445
|
-
* @returns string
|
|
446
|
-
*/
|
|
447
|
-
const getFileContentsFromGit = async (filePath) => {
|
|
448
|
-
return await gitClient().catFile(['blob', `HEAD:${filePath}`]);
|
|
449
|
-
};
|
|
450
|
-
/**
|
|
451
|
-
* Reads the file contents located on disk
|
|
452
|
-
* @param filename - the name of the file
|
|
453
|
-
* @returns string
|
|
454
|
-
*/
|
|
455
|
-
const getFileContentsFromDisk = async (filename) => {
|
|
456
|
-
return await fs.readFileSync(path.join(srcSvgBasePath, filename), 'utf8');
|
|
457
|
-
};
|
|
458
|
-
/**
|
|
459
|
-
* Creates an instance of the SimpleGit object
|
|
460
|
-
* @param options - list of SimpleGitOptions
|
|
461
|
-
* @returns SimpleGit client
|
|
462
|
-
*/
|
|
463
|
-
const gitClient = (options = { baseDir: srcSvgBasePath, binary: 'git' }) => {
|
|
464
|
-
return simpleGit(options);
|
|
465
|
-
};
|
|
466
|
-
/**
|
|
467
|
-
* Loads the figma-icon-config
|
|
468
|
-
*
|
|
469
|
-
* @params rootDir - The source directory
|
|
470
|
-
* @returns FigmaIconConfig object
|
|
471
|
-
*/
|
|
472
|
-
const loadFigmaIconConfig = async (rootDir) => {
|
|
473
|
-
try {
|
|
474
|
-
const configFile = path.resolve(path.join(rootDir, 'figma-icon-config.json'));
|
|
475
|
-
if (fs.existsSync(configFile)) {
|
|
476
|
-
log(info('Config file located at: ', detail(configFile)));
|
|
477
|
-
const strConfig = await fs.readFile(configFile, 'utf-8');
|
|
478
|
-
const config = JSON.parse(strConfig);
|
|
479
|
-
let hasError = false;
|
|
480
|
-
hasError || (hasError = setFigmaAccessToken(config));
|
|
481
|
-
hasError || (hasError = setFigmaFileId(config));
|
|
482
|
-
if (hasError) {
|
|
483
|
-
logErrorMessage('loadFigmaIconConfig', null);
|
|
484
|
-
process.exit(1);
|
|
485
|
-
}
|
|
486
|
-
return config;
|
|
487
|
-
}
|
|
488
|
-
}
|
|
489
|
-
catch (e) {
|
|
490
|
-
logErrorMessage('loadFigmaIconConfig', e);
|
|
491
|
-
process.exit(1);
|
|
492
|
-
}
|
|
493
|
-
};
|
|
494
|
-
/**
|
|
495
|
-
* The main process that invokes the Figma Export process
|
|
496
|
-
*
|
|
497
|
-
* @params rootDir - The initial starting directory
|
|
498
|
-
* @params config - The config data
|
|
499
|
-
*/
|
|
500
|
-
const processData = async (rootDir, config) => {
|
|
501
|
-
try {
|
|
502
|
-
config.downloadPath = path.join(rootDir, config.downloadPath);
|
|
503
|
-
let figmaFileId = config.figmaFileId;
|
|
504
|
-
let figmaData = await fetchFigmaData(figmaFileId);
|
|
505
|
-
if (config.branchName && figmaData.branches.length > 0) {
|
|
506
|
-
const branch = figmaData.branches.find(b => b.name === config.branchName);
|
|
507
|
-
if (!branch) {
|
|
508
|
-
// throw error(`No branch found with the name "${chalk.white.bgRed(config.branchName)}"`);
|
|
509
|
-
log(error('No branch found with the name'), chalk.white.bgRed(config.branchName));
|
|
510
|
-
process.exit(1);
|
|
511
|
-
}
|
|
512
|
-
figmaFileId = branch.key;
|
|
513
|
-
log(info('Found branch!! Retrieving data for Branch:', detail(config.branchName), ', Branch File id:', detail(figmaFileId)));
|
|
514
|
-
figmaData = await fetchFigmaData(figmaFileId);
|
|
515
|
-
}
|
|
516
|
-
const page = findPage(figmaData.document, config.pageName);
|
|
517
|
-
const response = await fs.emptyDir(config.downloadPath)
|
|
518
|
-
.then(() => {
|
|
519
|
-
return fetchAndDownloadIcons(page, figmaFileId, config, figmaData.components);
|
|
520
|
-
});
|
|
521
|
-
return response;
|
|
522
|
-
}
|
|
523
|
-
catch (e) {
|
|
524
|
-
logErrorMessage('processData', e);
|
|
525
|
-
}
|
|
526
|
-
};
|
|
527
|
-
/**
|
|
528
|
-
* Processes the SimpleGit status results and builds
|
|
529
|
-
* the HTML Section data
|
|
530
|
-
*
|
|
531
|
-
* @param results - list of results from SimpleGit.status
|
|
532
|
-
* @returns object - string html data for modifed, created, deleted
|
|
533
|
-
*/
|
|
534
|
-
const processStatusResults = async (results) => {
|
|
535
|
-
const { modified: m, created: n, deleted: d, renamed: r } = results;
|
|
536
|
-
let created, deleted, modified, renamed;
|
|
537
|
-
if (n.length > 0) {
|
|
538
|
-
created = await Promise.all(n.map((path) => { return buildBeforeAndAfterSvg('', path); }));
|
|
539
|
-
created = buildHTMLSection('Added', created);
|
|
540
|
-
}
|
|
541
|
-
if (d.length > 0) {
|
|
542
|
-
deleted = await Promise.all(d.map((path) => (buildBeforeAndAfterSvg('D', path))));
|
|
543
|
-
deleted = buildHTMLSection('Deleted', deleted);
|
|
544
|
-
}
|
|
545
|
-
if (m.length > 0) {
|
|
546
|
-
modified = await Promise.all(m.map((path) => (buildBeforeAndAfterSvg('M', path))));
|
|
547
|
-
modified = buildHTMLSection('Modified', modified);
|
|
548
|
-
}
|
|
549
|
-
if (r.length > 0) {
|
|
550
|
-
renamed = await Promise.all(r.map((path) => (buildBeforeAndAfterSvg('R', path.to, path.from))));
|
|
551
|
-
renamed = buildHTMLSection('Renamed', renamed);
|
|
552
|
-
}
|
|
553
|
-
return { created, deleted, modified, renamed };
|
|
554
|
-
};
|
|
555
|
-
/***************************/
|
|
556
|
-
/* Kicks off the Process */
|
|
557
|
-
/***************************/
|
|
558
|
-
console.log(path.join(__dirname, '../..'));
|
|
559
|
-
run(path.join(__dirname, '../..'));
|
|
560
|
-
/**
|
|
561
|
-
*
|
|
562
|
-
* Helper Methods
|
|
563
|
-
*
|
|
564
|
-
*
|
|
565
|
-
*/
|
|
566
|
-
/**
|
|
567
|
-
* Generates a string that represents the number
|
|
568
|
-
* of KiB
|
|
569
|
-
*
|
|
570
|
-
* @param size - number -
|
|
571
|
-
* @returns string
|
|
572
|
-
*/
|
|
573
|
-
const formatSize = (size) => {
|
|
574
|
-
return (size / 1024).toFixed(2) + ' KiB';
|
|
575
|
-
};
|
|
576
|
-
/**
|
|
577
|
-
* Logs an error message
|
|
578
|
-
* @param methodName - the name of the method the error occurred in
|
|
579
|
-
* @param err - the error
|
|
580
|
-
*/
|
|
581
|
-
const logErrorMessage = (methodName, err) => {
|
|
582
|
-
log('Error in ', detail(methodName), '\n Message: ', error(err));
|
|
583
|
-
};
|
|
584
|
-
/**
|
|
585
|
-
* Outputs a table of Name and Filesize for each
|
|
586
|
-
* file downloaded
|
|
587
|
-
*
|
|
588
|
-
* @param results - Collection of name and filesize
|
|
589
|
-
*/
|
|
590
|
-
const makeResultsTable = (results) => {
|
|
591
|
-
const ui = cliui({ width: 80 });
|
|
592
|
-
ui.div(makeRow(chalk.cyan.bold(`File`), chalk.cyan.bold(`Size`)) + `\n\n` +
|
|
593
|
-
results.map(asset => makeRow(asset.name.includes('-duplicate-name')
|
|
594
|
-
? chalk.red.bold(asset.name)
|
|
595
|
-
: chalk.green(asset.name), formatSize(asset.size))).join(`\n`));
|
|
596
|
-
return ui.toString();
|
|
597
|
-
};
|
|
598
|
-
const makeRow = (a, b) => {
|
|
599
|
-
return ` ${a}\t ${b}\t`;
|
|
600
|
-
};
|
|
601
|
-
/**
|
|
602
|
-
* Removes the tmp directory created during
|
|
603
|
-
* the download process from the FigmaAPI
|
|
604
|
-
*
|
|
605
|
-
* @param config - FigmaIconConfig object
|
|
606
|
-
*/
|
|
607
|
-
const removeTmpDirectory = (config) => {
|
|
608
|
-
log('Removing tmp directory');
|
|
609
|
-
const tmpDir = path.join(config.downloadPath, '..');
|
|
610
|
-
fs.rmSync(tmpDir, { force: true, recursive: true });
|
|
611
|
-
};
|
|
612
|
-
/**
|
|
613
|
-
* Reads and Sets the Figma access token
|
|
614
|
-
*
|
|
615
|
-
* @params config - FigmaIconConfig object
|
|
616
|
-
* @returns boolean - hasError occurred
|
|
617
|
-
*/
|
|
618
|
-
const setFigmaAccessToken = (config) => {
|
|
619
|
-
let hasError = false;
|
|
620
|
-
// Figma Token check
|
|
621
|
-
// Config file overrides Environment variable
|
|
622
|
-
switch (true) {
|
|
623
|
-
// Use Environment variable
|
|
624
|
-
case (!!process.env.FIGMA_ACCESS_TOKEN == true):
|
|
625
|
-
log(info('Using Figma Access Token in ', detail('ENVIRONMENT variable')));
|
|
626
|
-
config.figmaAccessToken = process.env.FIGMA_ACCESS_TOKEN;
|
|
627
|
-
break;
|
|
628
|
-
case (!!config.figmaAccessToken == true):
|
|
629
|
-
log(info('Using Figma Access Token in ', detail('CONFIGURATION file')));
|
|
630
|
-
break;
|
|
631
|
-
case (!config.figmaAccessToken && !process.env.FIGMA_ACCESS_TOKEN) == true:
|
|
632
|
-
hasError || (hasError = true);
|
|
633
|
-
log(error('No Figma Access Token has been provided!!!!!'));
|
|
634
|
-
break;
|
|
635
|
-
}
|
|
636
|
-
return hasError;
|
|
637
|
-
};
|
|
638
|
-
/**
|
|
639
|
-
* Sets the Figma file id
|
|
640
|
-
*
|
|
641
|
-
* @params config - FigmaIconConfig object
|
|
642
|
-
* @returns boolean - hasError occurred
|
|
643
|
-
*/
|
|
644
|
-
const setFigmaFileId = (config) => {
|
|
645
|
-
let hasError = false;
|
|
646
|
-
// Figma File Id check
|
|
647
|
-
// Config file overrides Environment Variable
|
|
648
|
-
switch (true) {
|
|
649
|
-
// Use Environment variable
|
|
650
|
-
case (!!process.env.FIGMA_FILE_ID == true):
|
|
651
|
-
log(info('Using Figma File Id in ', detail('ENVIROMENT variable')));
|
|
652
|
-
config.figmaFileId = process.env.FIGMA_FILE_ID;
|
|
653
|
-
break;
|
|
654
|
-
// Use provided token in config
|
|
655
|
-
case (!!config.figmaFileId == true):
|
|
656
|
-
log(info('Using Figma File Id in ', detail('Configuration file')));
|
|
657
|
-
break;
|
|
658
|
-
// Render error and exit process
|
|
659
|
-
case (!config.figmaFileId && !process.env.FIGMA_FILE_ID) == true:
|
|
660
|
-
hasError || (hasError = true);
|
|
661
|
-
log(error('No Figma File Id has been provided!!!!'));
|
|
662
|
-
break;
|
|
663
|
-
}
|
|
664
|
-
return hasError;
|
|
665
|
-
};
|
|
666
|
-
//# sourceMappingURL=figma-icon-export.js.map
|