Skip to content
This repository has been archived by the owner on May 29, 2020. It is now read-only.

Add possibility to rotate existing glyph with css transform #341

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,57 @@ module.exports = function(grunt) {
}]
}
},
css_rotate: {
src: 'test/src/*.svg',
dest: 'test/tmp/css_rotate',
options: {
cssRotate: {
odnoklassniki: {
90: 'odnoklassniki-90',
180: 'odnoklassniki-180',
270: 'odnoklassniki-270',
360: 'odnoklassniki-360',
0: 'odnoklassniki-0'
},
single: {
45: 'odnoklassniki-45',
},
doesNotExist: {
90: 'doesNotExist-90'
}
}
}
},
css_rotate_bootstrap: {
src: 'test/src/*.svg',
dest: 'test/tmp/css_rotate_bootstrap',
options: {
syntax: 'bootstrap',
cssRotate: {
odnoklassniki: {
90: 'odnoklassniki-90'
},
doesNotExist: {
90: 'doesNotExist-90'
}
}
}
},
css_rotate_less: {
src: 'test/src/*.svg',
dest: 'test/tmp/css_rotate_less',
options: {
stylesheet: 'less',
cssRotate: {
odnoklassniki: {
90: 'odnoklassniki-90'
},
doesNotExist: {
90: 'doesNotExist-90'
}
}
}
}
},
nodeunit: {
all: ['test/webfont_test.js']
Expand Down
15 changes: 15 additions & 0 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,21 @@ At compile-time each template will have access to the same context as the compil
#### execMaxBuffer
If you get stderr maxBuffer exceeded warning message, engine probably logged a lot of warning messages. To see this warnings run grunt in verbose mode `grunt --verbose`. To go over this warning you can try to increase buffer size by this option. Default value is `1024 * 200`

#### cssRotate
Type: `object` Default: `null`

If you want an existing glyph additionally as rotated variant with an angel between 1 and 259 degrees you can define it here. A new CSS rule is written and CSS transform is used to rotate.

```javascript
options: {
cssRotate: {
'name-of-the-existing-glyph': {
90: 'name-of-the-rotated-glyph' // the object key is the angel in degrees
}
}
}
```

### Config Examples

#### Simple font generation
Expand Down
16 changes: 14 additions & 2 deletions tasks/templates/bem.css
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,13 @@
<% if (stylesheet === 'less') { %>
.<%= classPrefix %><%= glyphs[glyphIdx] %> {
&:before {
content:"<% if (addLigatures) { %><%= glyphs[glyphIdx] %><% } else { %>\<%= codepoints[glyphIdx] %><% } %>";
content:"<% if (addLigatures) { %><%= glyphs[glyphIdx] %><% } else { %>\<%= codepoints[glyphIdx] %><% } %>";<% if (cssRotate[glyphs[glyphIdx]]) { %>
display: inline-block;
-webkit-transform: rotate(<%= cssRotate[glyphs[glyphIdx]] %>deg);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By the way, in 2016 we don’t need any of these prefixes ;-)

-moz-transform: rotate(<%= cssRotate[glyphs[glyphIdx]] %>deg);
-ms-transform: rotate(<%= cssRotate[glyphs[glyphIdx]] %>deg);
-o-transform: rotate(<%= cssRotate[glyphs[glyphIdx]] %>deg);
transform: rotate(<%= cssRotate[glyphs[glyphIdx]] %>deg);<% } %>
}<% if (ie7) {%>
*zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#x<%= codepoints[glyphIdx] %>;');
<% } %>
Expand All @@ -50,5 +56,11 @@
}
<% } %>
.<%= classPrefix %><%= glyphs[glyphIdx] %>:before {
content:"<% if (addLigatures) { %><%= glyphs[glyphIdx] %><% } else { %>\<%= codepoints[glyphIdx] %><% } %>";
content:"<% if (addLigatures) { %><%= glyphs[glyphIdx] %><% } else { %>\<%= codepoints[glyphIdx] %><% } %>";<% if (cssRotate[glyphs[glyphIdx]]) { %>
display: inline-block;
-webkit-transform: rotate(<%= cssRotate[glyphs[glyphIdx]] %>deg);
-moz-transform: rotate(<%= cssRotate[glyphs[glyphIdx]] %>deg);
-ms-transform: rotate(<%= cssRotate[glyphs[glyphIdx]] %>deg);
-o-transform: rotate(<%= cssRotate[glyphs[glyphIdx]] %>deg);
transform: rotate(<%= cssRotate[glyphs[glyphIdx]] %>deg);<% } %>
}<% } } } %>
16 changes: 14 additions & 2 deletions tasks/templates/bootstrap.css
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,13 @@ li[class*=" <%= classPrefix %>"].<%= classPrefix %>large:before {
<% if (stylesheet === 'less') { %>
.<%= classPrefix %><%= glyphs[glyphIdx] %> {
&:before {
content:"<% if (addLigatures) { %><%= glyphs[glyphIdx] %><% } else { %>\<%= codepoints[glyphIdx] %><% } %>";
content:"<% if (addLigatures) { %><%= glyphs[glyphIdx] %><% } else { %>\<%= codepoints[glyphIdx] %><% } %>";<% if (cssRotate[glyphs[glyphIdx]]) { %>
display: inline-block;
-webkit-transform: rotate(<%= cssRotate[glyphs[glyphIdx]] %>deg);
-moz-transform: rotate(<%= cssRotate[glyphs[glyphIdx]] %>deg);
-ms-transform: rotate(<%= cssRotate[glyphs[glyphIdx]] %>deg);
-o-transform: rotate(<%= cssRotate[glyphs[glyphIdx]] %>deg);
transform: rotate(<%= cssRotate[glyphs[glyphIdx]] %>deg);<% } %>
}
<% if (ie7) {%>
*zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#x<%= codepoints[glyphIdx] %>;');
Expand All @@ -107,6 +113,12 @@ li[class*=" <%= classPrefix %>"].<%= classPrefix %>large:before {
}
<% } %>
.<%= classPrefix %><%= glyphs[glyphIdx] %>:before {
content:"<% if (addLigatures) { %><%= glyphs[glyphIdx] %><% } else { %>\<%= codepoints[glyphIdx] %><% } %>";
content:"<% if (addLigatures) { %><%= glyphs[glyphIdx] %><% } else { %>\<%= codepoints[glyphIdx] %><% } %>";<% if (cssRotate[glyphs[glyphIdx]]) { %>
display: inline-block;
-webkit-transform: rotate(<%= cssRotate[glyphs[glyphIdx]] %>deg);
-moz-transform: rotate(<%= cssRotate[glyphs[glyphIdx]] %>deg);
-ms-transform: rotate(<%= cssRotate[glyphs[glyphIdx]] %>deg);
-o-transform: rotate(<%= cssRotate[glyphs[glyphIdx]] %>deg);
transform: rotate(<%= cssRotate[glyphs[glyphIdx]] %>deg);<% } %>
}<% } %>
<% } } %>
49 changes: 43 additions & 6 deletions tasks/webfont.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,8 @@ module.exports = function(grunt) {
cache: options.cache || path.join(__dirname, '..', '.cache'),
callback: options.callback,
customOutputs: options.customOutputs,
execMaxBuffer: options.execMaxBuffer || 1024 * 200
execMaxBuffer: options.execMaxBuffer || 1024 * 200,
cssRotate: options.cssRotate || {}
};

o = _.extend(o, {
Expand Down Expand Up @@ -332,6 +333,38 @@ module.exports = function(grunt) {
});
o.fontRawSrcs = fontSrcs;

if (typeof o.cssRotate === 'object' && Object.keys(o.cssRotate).length > 0) {
var cssRotate = {};
for (var glyph in o.cssRotate) {
var idx = o.glyphs.indexOf(glyph);
if (idx === -1) {
// we can only rotate an existing glyph
continue;
}
if (typeof o.cssRotate[glyph] === 'object' && Object.keys(o.cssRotate[glyph]).length > 0) {
var appendIdx = idx+1;
for (var deg in o.cssRotate[glyph]) {
if (!/^\d{1,3}$/.test(deg)) {
continue;
}
if (typeof deg !== 'number') {
deg = parseInt(deg, 10);
}
if (deg >= 360 || deg === 0 || o.glyphs.indexOf(o.cssRotate[glyph][deg]) !== -1) {
// existing glyph have priority before rotated and an angular degree lower than 1 or greather than 359 makes no sense
continue;
}
// append the rotated glyph direct after the source
o.glyphs.splice(appendIdx, 0, o.cssRotate[glyph][deg]);
o.codepoints[o.cssRotate[glyph][deg]] = o.codepoints[glyph];
cssRotate[o.cssRotate[glyph][deg]] = deg;
appendIdx++;
}
}
}
o.cssRotate = cssRotate;
}

// Convert codepoints to array of strings
var codepoints = [];
_.each(o.glyphs, function(name) {
Expand Down Expand Up @@ -415,11 +448,15 @@ module.exports = function(grunt) {

var htmlStyles;

// Prepare relative font paths for injection into @font-face refs in HTML
var relativeRe = new RegExp(_s.escapeRegExp(o.relativeFontPath), 'g');
var htmlRelativeFontPath = normalizePath(path.relative(o.destHtml, o.relativeFontPath));
var _fontSrc1 = o.fontSrc1.replace(relativeRe, htmlRelativeFontPath);
var _fontSrc2 = o.fontSrc2.replace(relativeRe, htmlRelativeFontPath);
var _fontSrc1 = o.fontSrc1;
var _fontSrc2 = o.fontSrc2;
if (o.relativeFontPath) {
// Prepare relative font paths for injection into @font-face refs in HTML
var relativeRe = new RegExp(_s.escapeRegExp(o.relativeFontPath), 'g');
var htmlRelativeFontPath = normalizePath(path.relative(o.destHtml, o.relativeFontPath));
_fontSrc1 = _fontSrc1.replace(relativeRe, htmlRelativeFontPath);
_fontSrc2 = _fontSrc2.replace(relativeRe, htmlRelativeFontPath);
}

_.extend(context, {
fontSrc1: _fontSrc1,
Expand Down
43 changes: 43 additions & 0 deletions test/webfont_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ exports.webfont = {
'Second EOT declaration.'
);

// the font is not embeded and we have no relative path. it should be at src:url("icons.eot")
test.ok(/@font-face\{[^}]+src:url\("icons.eot"\)[^}]+\}/.test(html.replace(/\s/g, '')), 'Font should be declared with src:url()');

// Every SVG file should have corresponding entry in CSS and HTML files
svgs.forEach(function(file, index) {
var id = path.basename(file, '.svg');
Expand Down Expand Up @@ -887,6 +890,46 @@ exports.webfont = {
// Files should render with custom context variables
test.ok(fs.existsSync('test/tmp/custom_output/context-test.html'));

test.done();
},

css_rotate: function(test) {
var css = grunt.file.read('test/tmp/css_rotate/icons.css').replace(/\s/g, '');

test.ok(/\.icon_odnoklassniki-90:before\{[^}]+transform:rotate\(90deg\);\}/.test(css), 'glyph odnoklassniki-90 with deg 90 should be in the CSS file');
test.ok(/\.icon_odnoklassniki-180:before\{[^}]+transform:rotate\(180deg\);\}/.test(css), 'glyph odnoklassniki-180 with deg 180 should be in the CSS file');
test.ok(/\.icon_odnoklassniki-270:before\{[^}]+transform:rotate\(270deg\);\}/.test(css), 'glyph odnoklassniki-270 with deg 270 should be in the CSS file');

test.ok(!/\.icon_odnoklassniki-270:before\{[^}]+transform:rotate\(271deg\);\}/.test(css), 'glyph odnoklassniki-270 with deg 271 should not be in the CSS file');

['odnoklassniki-360', 'odnoklassniki-0', 'doesNotExist', 'doesNotExist-90'].forEach(function(glyph) {
test.ok(!find(css, '.icon_'+glyph), 'glyph '+glyph+' should not be in the CSS file');
});

test.done();
},

css_rotate_bootstrap: function(test) {
var css = grunt.file.read('test/tmp/css_rotate_bootstrap/icons.css').replace(/\s/g, '');

test.ok(/\.icon-odnoklassniki-90:before\{[^}]+transform:rotate\(90deg\);\}/.test(css), 'glyph odnoklassniki-90 with deg 90 should be in the CSS file');

['doesNotExist', 'doesNotExist-90'].forEach(function(glyph) {
test.ok(!find(css, '.icon-'+glyph), 'glyph '+glyph+' should not be in the CSS file');
});

test.done();
},

css_rotate_less: function(test) {
var less = grunt.file.read('test/tmp/css_rotate_less/icons.less').replace(/\s/g, '');

test.ok(/\.icon_odnoklassniki-90\{&:before\{[^}]+transform:rotate\(90deg\);\}\}/.test(less), 'glyph odnoklassniki-90 with deg 90 should be in the LESS file');

['doesNotExist', 'doesNotExist-90'].forEach(function(glyph) {
test.ok(!find(less, '.icon_'+glyph), 'glyph '+glyph+' should not be in the LESS file');
});

test.done();
}

Expand Down