Skip to content

Commit

Permalink
Basic project structure
Browse files Browse the repository at this point in the history
  • Loading branch information
PKief committed Nov 8, 2023
1 parent c831a5e commit aaacc81
Show file tree
Hide file tree
Showing 19 changed files with 2,220 additions and 5,735 deletions.
7,517 changes: 2,053 additions & 5,464 deletions package-lock.json

Large diffs are not rendered by default.

12 changes: 7 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"vscode-icon-theme-reviewer": "./bin/cli.js"
},
"scripts": {
"start": "node ./bin/cli.js angular.svg",
"build": "tsc -p tsconfig.json",
"test": "jest",
"lint": "eslint -c .eslintrc.json --ext .ts ./src/**/*.ts",
Expand Down Expand Up @@ -57,16 +58,17 @@
"eslint": "^8.3.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-prettier": "^4.0.0",
"jest": "^29.7.0",
"ts-jest": "^29.1.1",
"ts-node": "^10.9.1",
"typescript": "^5.2.2"
"jest": "^27.5.0",
"ts-jest": "^27.1.3",
"ts-node": "^10.4.0",
"typescript": "^4.5.5"
},
"dependencies": {
"glob": "^7.2.0",
"is-glob": "^4.0.3",
"is-svg": "^4.3.2",
"js-yaml": "^4.1.0",
"minimist": "^1.2.5"
"minimist": "^1.2.5",
"puppeteer": "^21.5.0"
}
}
134 changes: 7 additions & 127 deletions src/cli/commands/printResults.ts
Original file line number Diff line number Diff line change
@@ -1,61 +1,13 @@
import isGlob from 'is-glob';
import isSvg from 'is-svg';
import * as yaml from 'js-yaml';
import { getSuggestions, isColorInPalette } from '../../core';
import { globAsync, readFileAsync } from '../../core/async';
import { ColorPalette, InvalidColorResult, Results } from '../../core/models';
import { isValidColor } from '../../core/utils';
import { green, red } from '../utils';
import { generatePreview } from '../../core';
import { globAsync } from '../../core/async';
import { Results } from '../../core/models';

const printResults = async (filePatterns: string[], colorFilePath: string) => {
const { invalidColorResults, base64Results, invalidSvgResults } =
await getResults(filePatterns, colorFilePath);

if (invalidSvgResults.length > 0) {
invalidSvgResults.forEach((result) => {
console.log(red(`⚠️ [${result.file}] Invalid SVG syntax`));
});
}

if (base64Results.length > 0) {
base64Results.forEach((result) => {
console.log(
red(
`⚠️ [${result.file}] Usage of base64 string, no guarantee that all colors are of the palette`
)
);
});
}

if (invalidColorResults.length > 0) {
invalidColorResults.forEach((result) => {
const suggestionsText =
result.suggestions.length > 0
? `Suggestions: [${result.suggestions.map((s) => s.hex).join(', ')}]`
: '';

const errorMessage = `⚠️ [${result.file}] Invalid color "${result.invalidColor}". ${suggestionsText}\n`;
console.log(red(errorMessage));
});
}

if (
invalidColorResults.length +
invalidSvgResults.length +
base64Results.length ===
0
) {
console.log(green('✅ All colors in all files are valid!'));
process.exit(0);
} else {
process.exit(1);
}
const printResults = async (filePatterns: string[]) => {
await getResults(filePatterns);
};

const getResults = async (
filePatterns: string[],
colorFilePath: string
): Promise<Results> => {
const getResults = async (filePatterns: string[]): Promise<Results> => {
const result: Results = {
invalidColorResults: [],
base64Results: [],
Expand All @@ -67,81 +19,9 @@ const getResults = async (
? await globAsync(filePattern)
: [filePattern];

for (const fileName of globFiles) {
const svgFileContent = await readSvgFile(fileName);
const colors = getColorsInFile(svgFileContent);

const palette = yaml.load(
await readFileAsync(colorFilePath, 'utf8')
) as ColorPalette;

if (containsBase64EncodedString(svgFileContent)) {
result.base64Results.push({ file: fileName, base64Error: true });
} else if (!isSvg(svgFileContent)) {
result.invalidSvgResults.push({ file: fileName, invalidSvg: true });
} else {
result.invalidColorResults.push(
...getInvalidColorsOfFile(colors, palette, fileName)
);
}
}
generatePreview(globFiles);
}
return result;
};

const readSvgFile = async (fileName: string) => {
try {
return await readFileAsync(fileName, 'utf8');
} catch (error) {
throw new Error(
`Could not read file "${fileName}". Make sure it exists on the file system.`
);
}
};

const getInvalidColorsOfFile = (
colors: string[],
palette: ColorPalette,
fileName: string
): InvalidColorResult[] => {
return colors.reduce<InvalidColorResult[]>((result, color) => {
if (!isValidColor(color)) {
result.push({
file: fileName,
invalidColor: color,
suggestions: [],
});
} else if (!isColorInPalette(color, palette.colors)) {
result.push({
file: fileName,
invalidColor: color,
suggestions: getSuggestions(color, palette.colors),
});
}
return result;
}, []);
};

const getColorsInFile = (fileContents: string): string[] => {
const colorPattern = new RegExp(/(fill|stop-color|stroke)="([^"]+)"/, 'gi');
const colorPatternCss = new RegExp(/(stroke|fill):\s?([^;"]+)/, 'gi');
const urlReference = new RegExp(/url\(#\w+\)/);

const colors = [
...fileContents.matchAll(colorPattern),
...fileContents.matchAll(colorPatternCss),
];

return [...colors]
.map((c) => c[2])
.filter((c) => c !== undefined)
.filter((c) => !c.match(urlReference))
.filter((c) => c !== 'none');
};

const containsBase64EncodedString = (fileContents: string): boolean => {
const base64Pattern = new RegExp('data:image/png;base64', 'gi');
return base64Pattern.test(fileContents);
};

export { printResults };
6 changes: 1 addition & 5 deletions src/cli/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,7 @@ const run = async () => {
return;
}

if (!args.colors) {
throw new Error('List of colors must be provided.');
}

await printResults(args._, args.colors);
await printResults(args._);
};

try {
Expand Down
1 change: 1 addition & 0 deletions src/core/demo/icons/angular.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions src/core/demo/icons/folder-dist-open.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
20 changes: 20 additions & 0 deletions src/core/demo/preview.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<!DOCTYPE html>
<head>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div class="theme-review">
<div class="theme-container dark">
<h2>Dark theme</h2>
<ul>
{{icons}}
</ul>
</div>
<div class="theme-container light">
<h2>Light Theme</h2>
<ul>
{{icons}}
</ul>
</div>
</div>
</body>
63 changes: 63 additions & 0 deletions src/core/demo/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
:root {
--main-bg-color: #1e1e1e;
--dark-theme-bg-color: #1e1e1e;
--dark-theme-font-color: #fafafa;
--light-theme-bg-color: #f3f3f3;
--light-theme-font-color: #424242;
}

body {
margin: 0;
padding: 0;
font-family: arial, sans-serif;
border-collapse: collapse;
width: 100%;
background: var(--main-bg-color);
font-size: 1rem;
}

.theme-review {
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr;
}

.theme-review ul {
list-style: none;
padding: 0;
margin: 0;
}

.theme-container {
padding: 20px;
}

.theme-container > h2 {
font-size: 1.25rem;
margin-top: 0;
}

.theme-container.dark {
color: var(--dark-theme-font-color);
background: var(--dark-theme-bg-color);
}

.theme-container.light {
color: var(--light-theme-font-color);
background: var(--light-theme-bg-color);
}

.icon {
display: flex;
align-items: center;
}

.icon > img {
width: 16px;
height: 22px;
padding-right: 6px;
}

.icon > span {
font-size: 13px;
}
32 changes: 32 additions & 0 deletions src/core/generate-preview.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { readFileSync, writeFileSync } from 'fs';
import { join } from 'path';
import { green, red } from '../cli/utils';
import { createScreenshot } from './utils/screenshot';

/**
* Generates
*
* @param fileNames List of SVG file names
*/
export const generatePreview = async (fileNames: string[]) => {
const previewFilePath = join('/demo/preview.html');
const previewFile = readFileSync(previewFilePath, 'utf8');

const placeholder = '{{icons}}';
const iconTemplate = fileNames.reduce((acc, fileName) => {
const iconName = fileName.split('.')[0];
return `${acc}<li><div class="icon"><img src="./icons/${fileName}" alt="${iconName}" /><span class="iconName">${iconName}</span></div></li>`;
}, '');
const finalTemplate = previewFile.replaceAll(placeholder, iconTemplate);
writeFileSync(previewFilePath + '_final.html', finalTemplate);

try {
await createScreenshot(previewFilePath + '_final.html', 'preview');
console.log(
'> Material Icon Theme:',
green(`Successfully created preview image!`)
);
} catch (error) {
throw Error(red(`Error while creating preview image`));
}
};
3 changes: 1 addition & 2 deletions src/core/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
export * from './validate';
export * from './suggestions';
export * from './generate-preview';
27 changes: 0 additions & 27 deletions src/core/suggestions.spec.ts

This file was deleted.

36 changes: 0 additions & 36 deletions src/core/suggestions.ts

This file was deleted.

3 changes: 1 addition & 2 deletions src/core/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
export * from './isValidColor';
export * from './toHex';
export * from './screenshot';
Loading

0 comments on commit aaacc81

Please sign in to comment.