Skip to content

Commit

Permalink
Base extension (#32)
Browse files Browse the repository at this point in the history
* Move extension factory to a separate package
  • Loading branch information
dirtybit authored Dec 8, 2020
1 parent d13d4ec commit d084370
Show file tree
Hide file tree
Showing 20 changed files with 1,936 additions and 310 deletions.
33 changes: 33 additions & 0 deletions packages/base-extension/codeGenerators/color.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import Color from "zeplin-extension-style-kit/values/color";
import {
getResources,
getParams,
generateIdentifier,
getUniqueFirstItems
} from "zeplin-extension-style-kit/utils";

export const colorCodeGenerator = ({
language,
createGenerator,
options: {
prefix = "",
separator = "\n",
suffix = ""
} = {},
isColorsFromParam
}) => (context, colorsParam) => {
const params = getParams(context);
const generator = createGenerator(context, params);
const allColors = isColorsFromParam
? colorsParam
: getResources({ context, useLinkedStyleguides: params.useLinkedStyleguides, key: "colors" });
const uniqueColors = getUniqueFirstItems(allColors,
(color, other) => generateIdentifier(color.name) === generateIdentifier(other.name)
);
const code = `${prefix}${uniqueColors.map(c => generator.variable(c.name, new Color(c))).join(separator)}${suffix}`;

return {
code,
language
};
};
78 changes: 78 additions & 0 deletions packages/base-extension/codeGenerators/layer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import Layer from "zeplin-extension-style-kit/elements/layer";
import RuleSet from "zeplin-extension-style-kit/ruleSet";
import Mixin from "zeplin-extension-style-kit/declarations/mixin";
import {
getResources,
getUniqueLayerTextStyles,
selectorize,
isHtmlTag,
getParams,
generateIdentifier,
getUniqueFirstItems
} from "zeplin-extension-style-kit/utils";

export const layerCodeGenerator = ({
language,
createGenerator,
options: {
separator = "\n\n"
} = {}
}) => (context, selectedLayer) => {
const params = getParams(context);
const { useMixin } = params;
const generator = createGenerator(context, params);

const l = new Layer(selectedLayer, params);
const layerRuleSet = l.style;
const childrenRuleSet = [];
const { defaultTextStyle } = selectedLayer;

if (selectedLayer.type === "text" && defaultTextStyle) {
const textStyles = getUniqueFirstItems(getResources({
context,
useLinkedStyleguides: params.useLinkedStyleguides,
key: "textStyles"
}), (textStyle, other) => generateIdentifier(textStyle.name) === generateIdentifier(other.name));
const containerTextStyle = textStyles.find(textStyle => (
defaultTextStyle.conforms ? defaultTextStyle.conforms(textStyle) : defaultTextStyle.equals(textStyle)
));

const declarations = l.getLayerTextStyleDeclarations(defaultTextStyle);
const textStyleName = containerTextStyle && containerTextStyle.name;

if (useMixin && textStyleName && !isHtmlTag(selectorize(textStyleName))) {
const mixinRuleSet = new RuleSet("mixin", l.getLayerTextStyleDeclarations(containerTextStyle));

declarations.forEach(d => {
if (!mixinRuleSet.hasProperty(d.name)) {
layerRuleSet.addDeclaration(d);
}
});

layerRuleSet.addDeclaration(new Mixin(selectorize(textStyleName).replace(/^\./, "")));
} else {
declarations.forEach(d => layerRuleSet.addDeclaration(d));
}

getUniqueLayerTextStyles(selectedLayer).filter(
textStyle => !defaultTextStyle.equals(textStyle)
).forEach((textStyle, idx) => {
childrenRuleSet.push(
new RuleSet(
`${selectorize(selectedLayer.name)} ${selectorize(`text-style-${idx + 1}`)}`,
l.getLayerTextStyleDeclarations(textStyle)
)
);
});
}

const layerStyle = generator.ruleSet(layerRuleSet);
const childrenStyles = childrenRuleSet.map(
s => generator.ruleSet(s, { parentDeclarations: layerRuleSet.declarations })
);

return {
code: [layerStyle, ...childrenStyles].join(separator),
language
};
};
39 changes: 39 additions & 0 deletions packages/base-extension/codeGenerators/spacing.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import Length from "zeplin-extension-style-kit/values/length";
import {
getResources,
getParams,
generateIdentifier,
getUniqueFirstItems
} from "zeplin-extension-style-kit/utils";
const useRemUnitForMeasurement = ({ useForMeasurements }) => useForMeasurements;

export const spacingCodeGenerator = ({
language,
createGenerator,
options: {
prefix = "",
separator = "\n",
suffix = ""
} = {}
}) => context => {
const params = getParams(context);
const cssGenerator = createGenerator(context, params);
const spacingSections = getResources({ context, useLinkedStyleguides: params.useLinkedStyleguides, key: "spacingSections" });
const spacingTokens = getUniqueFirstItems(
spacingSections.map(({ spacingTokens: items }) => items).reduce((prev, current) => [...prev, ...current]),
(token, other) => generateIdentifier(token.name) === generateIdentifier(other.name)
);

const code = `${prefix}${
spacingTokens
.map(({ name, value }) => cssGenerator.variable(
name,
new Length(value, { useRemUnit: useRemUnitForMeasurement, useDensityDivisor: false })),
)
.join(separator)
}${suffix}`;
return {
code,
language
};
};
49 changes: 49 additions & 0 deletions packages/base-extension/codeGenerators/textStyle.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import FontFace from "zeplin-extension-style-kit/elements/fontFace";
import TextStyle from "zeplin-extension-style-kit/elements/textStyle";
import {
generateIdentifier,
getResources,
getFontFaces,
getParams,
getUniqueFirstItems
} from "zeplin-extension-style-kit/utils";

export const textStyleCodeGenerator = ({
language,
createGenerator,
options: {
prefix = "",
separator = "\n\n",
fontFaceSeparator = separator,
textStyleSeparator = separator,
suffix = ""
} = {},
isTextStylesFromParam
}) => (context, textStylesParam) => {
const params = getParams(context);
const generator = createGenerator(context, params);
const textStyles = isTextStylesFromParam
? textStylesParam
: getResources({ context, useLinkedStyleguides: params.useLinkedStyleguides, key: "textStyles" });

const uniqueTextStyles = getUniqueFirstItems(textStyles,
(textStyle, other) => generateIdentifier(textStyle.name) === generateIdentifier(other.name));
const fontFaces = getFontFaces(uniqueTextStyles);

const fontFaceCode = fontFaces.map(ts => {
const { style } = new FontFace(ts);

return generator.atRule(style);
}).join(fontFaceSeparator);

const textStyleCode = uniqueTextStyles.map(t => {
const { style } = new TextStyle(t);

return generator.ruleSet(style, { mixin: params.useMixin });
}).join(textStyleSeparator);

return {
code: `${prefix}${fontFaceCode}${separator}${textStyleCode}${suffix}`,
language
};
};
126 changes: 126 additions & 0 deletions packages/base-extension/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
import Color from "zeplin-extension-style-kit/values/color";
import { getResources, generateIdentifier, getUniqueFirstItems } from "zeplin-extension-style-kit/utils";
import { colorCodeGenerator } from "./codeGenerators/color";
import { layerCodeGenerator } from "./codeGenerators/layer";
import { spacingCodeGenerator } from "./codeGenerators/spacing";
import { textStyleCodeGenerator } from "./codeGenerators/textStyle";

const comment = (context, text) => `/* ${text} */`;

const exportColorsGenerator = ({
colors,
options: {
prefix = "",
suffix = ""
} = {}
}) => (context, colorsParam) => {
const { code, language } = colors(context, colorsParam);
return {
code: `${prefix}${code}${suffix}`,
filename: `colors.${language}`,
language
};
};

const exportTextStylesGenerator = ({
textStyles,
options: {
prefix = "",
suffix = ""
} = {}
}) => (context, textStylesParam) => {
const { code, language } = textStyles(context, textStylesParam);
return {
code: `${prefix}${code}${suffix}`,
filename: `fonts.${language}`,
language
};
};

const exportSpacingGenerator = ({
spacing,
options: {
prefix = "",
suffix = ""
} = {}
}) => context => {
const { code, language } = spacing(context);
return {
code: `${prefix}${code}${suffix}`,
filename: `spacing.${language}`,
language
};
};

export const createExtension = ({
language,
Generator,
colorsOptions,
textStylesOptions,
spacingOptions,
layerOptions,
exportColorsOptions,
exportTextStylesOptions,
exportSpacingOptions
}) => {
const getVariableMap = containerColors => {
const variables = {};

containerColors.forEach(containerColor => {
// Colors are sorted by their priorities; so, we don't override already set colors
const colorValue = new Color(containerColor).valueOf();
variables[colorValue] = variables[colorValue] ? variables[colorValue] : containerColor.name;
});

return variables;
};

const createGenerator = (context, params) => {
const containerColors = getResources({ context, useLinkedStyleguides: params.useLinkedStyleguides, key: "colors" });
const uniqueColors = getUniqueFirstItems(containerColors,
(color, other) => generateIdentifier(color.name) === generateIdentifier(other.name)
);

return new Generator(getVariableMap(uniqueColors), params);
};

const colors = colorCodeGenerator({ language, createGenerator, options: colorsOptions });
const textStyles = textStyleCodeGenerator({ language, createGenerator, options: textStylesOptions });
const spacing = spacingCodeGenerator({ language, createGenerator, options: spacingOptions });
const layer = layerCodeGenerator({ language, createGenerator, options: layerOptions });
const exportColors = exportColorsGenerator({ colors, options: exportColorsOptions });
const exportTextStyles = exportTextStylesGenerator({ textStyles, options: exportTextStylesOptions });
const exportSpacing = exportSpacingGenerator({ spacing, options: exportSpacingOptions });
const styleguideColors = colorCodeGenerator({
language,
createGenerator,
options: colorsOptions,
isColorsFromParam: true
});
const styleguideTextStyles = textStyleCodeGenerator({
language,
createGenerator,
options: textStylesOptions,
isTextStylesFromParam: true
});
const exportStyleguideColors = exportColorsGenerator({ colors: styleguideColors, options: exportColorsOptions });
const exportStyleguideTextStyles = exportTextStylesGenerator({
textStyles: styleguideTextStyles,
options: exportTextStylesOptions
});

return {
colors,
textStyles,
spacing,
layer,
comment,
exportColors,
exportTextStyles,
exportSpacing,
styleguideColors,
styleguideTextStyles,
exportStyleguideColors,
exportStyleguideTextStyles
};
};
Loading

0 comments on commit d084370

Please sign in to comment.