Skip to content
Open
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
22 changes: 22 additions & 0 deletions lib/__tests__/lib.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,28 @@ describe('stilr', () => {
}
});

it('handles custom names tags correctly', () => {
StyleSheet.create({
mytag: { color: 'tomato' }
}, {
selector: tag => `.SomeParent .${tag}`
});

const css = StyleSheet.render();
assert.equal(css, '.SomeParent .mytag{color:tomato;}')
});

it('handles multiple custom names tags correctly', () => {
StyleSheet.create({
tag: { color: 'tomato' }
}, {
selector: tag => `.One .${tag}, .Two .${tag}`
});

const css = StyleSheet.render();
assert.equal(css, '.One .tag, .Two .tag{color:tomato;}')
});

it('outputs pseudo classes correctly', () => {
const hover = /(\._[\s\S]+)(:hover{)/g;

Expand Down
2 changes: 1 addition & 1 deletion lib/__tests__/utils.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ describe('utils', () => {
const STYLES_CSS = 'width:10px;height:10px;color:tomato;';

describe('#createClassName(obj)', () => {
const className = utils.createClassName( STYLES );
const className = utils.createClassName( null, null, STYLES );

it('retuns a class string', () => {
assert.equal( typeof className, 'string', `${ className } , should be string`);
Expand Down
24 changes: 19 additions & 5 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,23 @@ let globalStylesheet = new Map();

export default {
create( styles, stylesheet = globalStylesheet ) {
let options

if ( !(stylesheet instanceof Map) ) {
// options passed instead
options = stylesheet
stylesheet = globalStylesheet

if (options.selector)
stylesheet.customTags = true
}

if ( !(stylesheet instanceof Map) ) throw new Error(`${ stylesheet } should be a Map`);

return Object.keys( styles ).reduce( ( acc, key ) => {

let { style, pseudos, mediaQueries } = seperateStyles( styles[key] );
const className = createClassName( sortObject( style ));
let { style, pseudos, mediaQueries } = seperateStyles( options, key, styles[key] );
const className = createClassName(options, key, sortObject(style));

if (className === undefined) {
acc[ key ] = '';
Expand All @@ -28,7 +39,7 @@ export default {
if ( pseudos.length ) {
pseudos.map( selector => {
delete style[selector];
const pseudoClassName = `${className}${selector}`;
const pseudoClassName = `.${className}${selector}`;

if ( stylesheet.has( pseudoClassName ) ) return false;

Expand Down Expand Up @@ -77,6 +88,7 @@ export default {
}

acc[ key ] = className;

return acc;
}, {});
},
Expand All @@ -101,9 +113,11 @@ export default {
}

const markup = createMarkup( styles );
const prefix = stylesheet.customTags ? '' : '.'

css += options.pretty
? `.${ className } {\n${ markup.split(';').join(';\n')}}\n`
: `.${ className }{${ markup }}`;
? `${prefix}${ className } {\n${ markup.split(';').join(';\n')}}\n`
: `${prefix}${ className }{${ markup }}`;
}

return css + mediaQueries;
Expand Down
33 changes: 25 additions & 8 deletions lib/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,11 @@ export function extendedToString(num, base) {
return (base < 11) ? parseInt(conversion) : conversion;
}

export function createClassName(obj) {
export function createClassName(options, tag, obj) {
if (options && options.selector) {
return options.selector(tag)
}

const hash = extendedToString( createHash( stringifyObject(obj) ), 62);
return hash
? '_' + hash
Expand All @@ -62,16 +66,28 @@ export function isEmpty(obj) {
return !Object.keys(obj).length;
}

const pseudos = {
active: ':active',
hover: ':hover',
focus: ':focus',
link: ':link',
visited: ':visited',
checked: ':checked',
disabled: ':disabled',
empty: ':empty',
invalid: ':invalid',
}

export function isPseudo({ style, rule }) {
return rule.charAt(0) === ':' && typeof style === 'object';
return (rule.charAt(0) === ':' || pseudos[rule]) && typeof style === 'object';
}

export function isMediaQuery({ style, rule }) {
return rule.charAt(0) === '@' && typeof style === 'object';
}

function handle(type, acc, { style, rule }, pseudos = []) {
const hash = createClassName( sortObject( style ));
function handle(options, tag, type, acc, { style, rule }, pseudos = []) {
const hash = createClassName( options, tag, sortObject( style ));
const rules = pseudos.length
? [[].concat(rule, style, pseudos)]
: rule;
Expand All @@ -82,20 +98,21 @@ function handle(type, acc, { style, rule }, pseudos = []) {
}


export function seperateStyles (styles) {
export function seperateStyles (options, tag, styles) {
return Object.keys(styles).reduce( (acc, rule) => {
const content = {
style: styles[rule],
rule
};

if ( isPseudo( content ) ) {
return handle('pseudos', acc, content );
if (pseudos[rule]) content.rule = pseudos[rule] // translate to :active
return handle(options, tag, 'pseudos', acc, content );
}

if ( isMediaQuery( content ) ) {
const { style, pseudos } = seperateStyles( content.style );
return handle('mediaQueries', acc, { rule, style }, pseudos );
const { style, pseudos } = seperateStyles( options, tag, content.style );
return handle(options, tag, 'mediaQueries', acc, { rule, style }, pseudos );
}

acc.style[rule] = content.style;
Expand Down