Skip to content

Commit

Permalink
feat: Add support for LESS asset type (#11)
Browse files Browse the repository at this point in the history
  • Loading branch information
ernstc authored Mar 20, 2024
1 parent 362ec65 commit 1fa8c59
Show file tree
Hide file tree
Showing 8 changed files with 199 additions and 1 deletion.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ Options:
-o, --output <value> specify output directory
-n, --name <value> base name of the font set used both as default asset name (default: icons)
-t, --font-types <value...> specify font formats to generate (default: eot, woff2, woff, available: eot, woff2, woff, ttf, svg)
-g --asset-types <value...> specify other asset types to generate (default: css, html, json, ts, available: css, scss, sass, html, json, ts)
-g --asset-types <value...> specify other asset types to generate (default: css, html, json, ts, available: css, less, scss, sass, html, json, ts)
-h, --font-height <value> the output font height (icons will be scaled so the highest has this height) (default: 300)
--descent <value> the font descent
--normalize [bool] normalize icons by scaling them to the height of the highest icon
Expand Down
1 change: 1 addition & 0 deletions src/core/__tests__/config-parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ const mockConfig = {
fontsUrl: '/fonts',
templates: {
css: 'css',
less: 'less',
sass: 'sass',
scss: 'scss',
html: 'html'
Expand Down
61 changes: 61 additions & 0 deletions src/generators/asset-types/__tests__/__snapshots__/less.ts.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`\`LESS\` asset generator renders LESS correctly with \`selector\` option 1`] = `
"@test-font: "test";
@font-face {
font-display: block;
font-family: @test-font;
src: "::src-attr::";
}
.my-selector::before {
font-family: test !important;
font-style: normal;
font-weight: normal !important;
font-variant: normal;
text-transform: none;
line-height: 1;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
@test-map: {
my-icon: "\\f101";
}
.my-selector.tf-my-icon::before {
content: @test-map[my-icon];
}
"
`;

exports[`\`LESS\` asset generator renders LESS correctly with prefix and tag name options 1`] = `
"@test-font: "test";
@font-face {
font-display: block;
font-family: @test-font;
src: "::src-attr::";
}
b[class^="tf-"]::before, b[class*=" tf-"]::before {
font-family: test !important;
font-style: normal;
font-weight: normal !important;
font-variant: normal;
text-transform: none;
line-height: 1;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
@test-map: {
my-icon: "\\f101";
}
.tf-my-icon::before {
content: @test-map[my-icon];
}
"
`;
77 changes: 77 additions & 0 deletions src/generators/asset-types/__tests__/less.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import lessGen from '../less';
import { renderSrcAttribute } from '../../../utils/css';
import { resolve } from 'path';

const renderSrcMock = renderSrcAttribute as any as jest.Mock;

const mockOptions = {
name: 'test',
prefix: 'tf',
tag: 'b',
codepoints: { 'my-icon': 0xf101 },
assets: { 'my-icon': null },
templates: {
less: resolve(__dirname, '../../../../templates/less.hbs')
}
} as any;

jest.mock('../../../utils/css', () => ({
renderSrcAttribute: jest.fn(() => '"::src-attr::"')
}));

describe('`LESS` asset generator', () => {
beforeEach(() => {
renderSrcMock.mockClear();
});

test('renders LESS correctly with prefix and tag name options', async () => {
expect(
await lessGen.generate(mockOptions, Buffer.from(''))
).toMatchSnapshot();
});

test('renders LESS correctly with `selector` option', async () => {
expect(
await lessGen.generate(
{ ...mockOptions, selector: '.my-selector' },
Buffer.from('')
)
).toMatchSnapshot();
});

test('calls renderSrcAttribute correctly and includes its return value in the rendered template', async () => {
const fontBuffer = Buffer.from('::svg-content::');

const result = await lessGen.generate(mockOptions, fontBuffer);

expect(renderSrcMock).toHaveBeenCalledTimes(1);
expect(renderSrcMock).toHaveBeenCalledWith(mockOptions, fontBuffer);
expect(result).toContain('::src-attr::');
});

test('renders expected selector blocks', async () => {
const less = await lessGen.generate(mockOptions, Buffer.from(''));

expect(less).toContain(
'b[class^="tf-"]::before, b[class*=" tf-"]::before {'
);
expect(less).toContain('.tf-my-icon::before {');
});

test('renders expected variables', async () => {
const less = await lessGen.generate(mockOptions, Buffer.from(''));

expect(less).toContain('@test-font:');
expect(less).toContain('@test-map:');
});

test('renders expected selector blocks with `selector` option', async () => {
const less = await lessGen.generate(
{ ...mockOptions, selector: '.my-selector' },
Buffer.from('')
);

expect(less).toContain('.my-selector::before {');
expect(less).toContain('.my-selector.tf-my-icon::before {');
});
});
2 changes: 2 additions & 0 deletions src/generators/asset-types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import css from './css';
import html from './html';
import json from './json';
import ts from './ts';
import less from './less';
import sass from './sass';
import scss from './scss';

Expand All @@ -22,6 +23,7 @@ const generators: { [key in AssetType]: FontGenerator<any> } = {
[OtherAssetType.HTML]: html,
[OtherAssetType.JSON]: json,
[OtherAssetType.TS]: ts,
[OtherAssetType.LESS]: less,
[OtherAssetType.SASS]: sass,
[OtherAssetType.SCSS]: scss
};
Expand Down
17 changes: 17 additions & 0 deletions src/generators/asset-types/less.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { FontGenerator } from '../../types/generator';
import { FontAssetType } from '../../types/misc';
import { renderTemplate } from '../../utils/template';
import { renderSrcAttribute } from '../../utils/css';

const generator: FontGenerator<Buffer> = {
dependsOn: FontAssetType.SVG,

generate: (options, svg: Buffer) =>
renderTemplate(
options.templates.less,
{ ...options, fontSrc: renderSrcAttribute(options, svg) },
{ helpers: { codepoint: str => str.toString(16) } }
)
};

export default generator;
2 changes: 2 additions & 0 deletions src/types/misc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export enum FontAssetType {

export enum OtherAssetType {
CSS = 'css',
LESS = 'less',
SCSS = 'scss',
SASS = 'sass',
HTML = 'html',
Expand All @@ -18,6 +19,7 @@ export enum OtherAssetType {
export const ASSET_TYPES_WITH_TEMPLATE = [
OtherAssetType.CSS,
OtherAssetType.HTML,
OtherAssetType.LESS,
OtherAssetType.SCSS,
OtherAssetType.SASS
];
Expand Down
38 changes: 38 additions & 0 deletions templates/less.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
@{{ name }}-font: "{{ name }}";

@font-face {
font-display: block;
font-family: @{{ name }}-font;
src: {{{ fontSrc }}};
}

{{# if selector }}
{{ selector }}::before {
{{ else }}
{{ tag }}[class^="{{prefix}}-"]::before, {{ tag }}[class*=" {{prefix}}-"]::before {
{{/ if }}
font-family: {{ name }} !important;
font-style: normal;
font-weight: normal !important;
font-variant: normal;
text-transform: none;
line-height: 1;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}

@{{ name }}-map: {
{{# each codepoints }}
{{ @key }}: "\\{{ codepoint this }}";
{{/ each }}
}

{{# each codepoints }}
{{# if ../selector }}
{{ ../selector }}.{{ ../prefix }}-{{ @key }}::before {
{{ else }}
{{ tag }}.{{ ../prefix }}-{{ @key }}::before {
{{/ if }}
content: @{{ ../name }}-map[{{ @key }}];
}
{{/ each }}

0 comments on commit 1fa8c59

Please sign in to comment.