New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support async mixins #18

Closed
jedmao opened this Issue Jul 17, 2015 · 6 comments

Comments

Projects
None yet
2 participants
@jedmao
Contributor

jedmao commented Jul 17, 2015

What do you think about supporting async mixins for mixins that return a promise? I think this would be excellent for a sprite mixin, for example, where some file I/O is required.

@ai

This comment has been minimized.

Show comment
Hide comment
@ai

ai Jul 18, 2015

Member

Ouh, It looks normal in first loook. But mayb in this case you should create separated plugin.

PostCSS mixins is not a Sass mixins. In Sass you do all stuff by mixins. In PostCSS mixins is a small part of CSS, that you want to copy. So there is no sense to async templates in PostCSS mixins, because they became to complicated to be just a templates.

Member

ai commented Jul 18, 2015

Ouh, It looks normal in first loook. But mayb in this case you should create separated plugin.

PostCSS mixins is not a Sass mixins. In Sass you do all stuff by mixins. In PostCSS mixins is a small part of CSS, that you want to copy. So there is no sense to async templates in PostCSS mixins, because they became to complicated to be just a templates.

@ai ai closed this Jul 18, 2015

@ai

This comment has been minimized.

Show comment
Hide comment
@ai

ai Jul 18, 2015

Member

What exactly you want to do? Let’s find the best solution (maybe it would a mixin).

Member

ai commented Jul 18, 2015

What exactly you want to do? Let’s find the best solution (maybe it would a mixin).

@jedmao

This comment has been minimized.

Show comment
Hide comment
@jedmao

jedmao Jul 18, 2015

Contributor

I already have a very strong sprite mixin that's working excellently right now via gulp.spritesmith, but that's only for the gulp build. I introduced postcss-middleware so that I could serve CSS via Express. Unfortunately, since I can't asynchronously return declarations in a mixin and I wasn't keen on the idea of doing intermediate file dumps, I just hijacked the sprite mixin and had it base-64 encode requested images directly in the CSS (background-image, width, height).

In the end, I kind of like the approach. It's definitely much faster; however, it's not 1:1 with the build process and so that has the potential to introduce strange visual issues on production vs. development.

I've definitely seen postcss-sprites, but I'm not keen on the input syntax. Maybe I should write a plugin that transpiles @sprite folder image; into the proper background image and dimension declarations.

What do you think?

Contributor

jedmao commented Jul 18, 2015

I already have a very strong sprite mixin that's working excellently right now via gulp.spritesmith, but that's only for the gulp build. I introduced postcss-middleware so that I could serve CSS via Express. Unfortunately, since I can't asynchronously return declarations in a mixin and I wasn't keen on the idea of doing intermediate file dumps, I just hijacked the sprite mixin and had it base-64 encode requested images directly in the CSS (background-image, width, height).

In the end, I kind of like the approach. It's definitely much faster; however, it's not 1:1 with the build process and so that has the potential to introduce strange visual issues on production vs. development.

I've definitely seen postcss-sprites, but I'm not keen on the input syntax. Maybe I should write a plugin that transpiles @sprite folder image; into the proper background image and dimension declarations.

What do you think?

@jedmao

This comment has been minimized.

Show comment
Hide comment
@jedmao

jedmao Jul 18, 2015

Contributor

The sprite mixin is actually fairly simple. It's getting the sprite data INTO the mixin that's a bit challenging. Here's my sprite mixin:

import {
    isUndefined
} from 'lodash';
import {
    func,
    Obj,
    Str
} from 'tcomb';

export default function sprite(options) {

    options = options || {};

    if (!options.spriteData) {
        throw new Error('missing option: spriteData');
    }

    return func([Obj, Str, Str], Obj)
        .of((mixin, sheet, imageName) => {
            let sheetData = options.spriteData[sheet];
            if (isUndefined(sheetData)) {
                throw new Error(`Sprite data not found for sheet: ${sheet}`);
            }
            let imageData = sheetData[imageName];
            if (isUndefined(imageData)) {
                throw new Error(`Sprite data not found for sheet: ${sheet}, image: ${imageName}`);
            }
            return {
                'background-image': `url(../images/sprites/${imageData.image})`,
                'background-position': [
                    `${imageData.offset_x}px`,
                    `${imageData.offset_y}px`
                ].join(' '),
                width: `${imageData.width}px`,
                height: `${imageData.height}px`
            };
        }
    );
}
Contributor

jedmao commented Jul 18, 2015

The sprite mixin is actually fairly simple. It's getting the sprite data INTO the mixin that's a bit challenging. Here's my sprite mixin:

import {
    isUndefined
} from 'lodash';
import {
    func,
    Obj,
    Str
} from 'tcomb';

export default function sprite(options) {

    options = options || {};

    if (!options.spriteData) {
        throw new Error('missing option: spriteData');
    }

    return func([Obj, Str, Str], Obj)
        .of((mixin, sheet, imageName) => {
            let sheetData = options.spriteData[sheet];
            if (isUndefined(sheetData)) {
                throw new Error(`Sprite data not found for sheet: ${sheet}`);
            }
            let imageData = sheetData[imageName];
            if (isUndefined(imageData)) {
                throw new Error(`Sprite data not found for sheet: ${sheet}, image: ${imageName}`);
            }
            return {
                'background-image': `url(../images/sprites/${imageData.image})`,
                'background-position': [
                    `${imageData.offset_x}px`,
                    `${imageData.offset_y}px`
                ].join(' '),
                width: `${imageData.width}px`,
                height: `${imageData.height}px`
            };
        }
    );
}
@jedmao

This comment has been minimized.

Show comment
Hide comment
@jedmao

jedmao Jul 18, 2015

Contributor

My gulp task and Express server both call this createPostcssProcessors function, which looks something like this...

export default function createPostcssProcessors(options) {
    options = options || {};
    let mixins = {};
    if (options.spriteData) {
        mixins.sprite = require('../mixins/sprite')(pick(options, 'spriteData'));
    }
    mixins = postcssMixins({
        mixinsFiles: join(__dirname, '..', 'mixins', '!(*.spec.js)'),
        mixins: assign(mixins, options.mixins)
    });
    // ...
}
Contributor

jedmao commented Jul 18, 2015

My gulp task and Express server both call this createPostcssProcessors function, which looks something like this...

export default function createPostcssProcessors(options) {
    options = options || {};
    let mixins = {};
    if (options.spriteData) {
        mixins.sprite = require('../mixins/sprite')(pick(options, 'spriteData'));
    }
    mixins = postcssMixins({
        mixinsFiles: join(__dirname, '..', 'mixins', '!(*.spec.js)'),
        mixins: assign(mixins, options.mixins)
    });
    // ...
}
@ai

This comment has been minimized.

Show comment
Hide comment
@ai

ai Jul 18, 2015

Member

You use a Sass way for mixins here. Mixins in PostCSS are just a smalll templates to reduce duplication. PostCSS mixins is not for such compplicated tasks like sprite. So you should make a plugin, not a mixin.

Member

ai commented Jul 18, 2015

You use a Sass way for mixins here. Mixins in PostCSS are just a smalll templates to reduce duplication. PostCSS mixins is not for such compplicated tasks like sprite. So you should make a plugin, not a mixin.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment