Skip to content

Commit

Permalink
Merge pull request #15 from artemnovichkov/feature/refactoring
Browse files Browse the repository at this point in the history
Refactoring helper functions to Zepcode singleton
  • Loading branch information
baybara-pavel authored Mar 22, 2018
2 parents 85144e6 + 691b1d4 commit 19bb345
Show file tree
Hide file tree
Showing 7 changed files with 215 additions and 87 deletions.
Binary file added .github/LinearGradientPlayground.zip
Binary file not shown.
10 changes: 1 addition & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,15 +89,7 @@

<details><summary>Linear gradient example</summary>

```swift
let gradientLayer = CAGradientLayer()
gradientLayer.frame = view.bounds
gradientLayer.startPoint = CGPoint(x: 0.0, y: 0.5)
gradientLayer.endPoint = CGPoint(x: 1.0, y: 0.5)
gradientLayer.colors = [UIColor.lightishRed.cgColor, UIColor.barbiePink.cgColor]
gradientLayer.locations = [0, 1]
view.layer.insertSublayer(gradientLayer, at: 0)
```
Check out [LinearGradientPlayground](.github/LinearGradientPlayground.zip) and read explanation of the implementation [here](https://github.com/artemnovichkov/zepcode/issues/1#issuecomment-370118449).

</details>
<details><summary>Radial gradient example</summary>
Expand Down
16 changes: 1 addition & 15 deletions src/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,25 +42,12 @@ export function generateFontExtension(textStyles) {
};
}

export function options(context) {
return {
useColorNames: context.getOption('use_color_names'),
useCustomColorInitializer: context.getOption(
'use_custom_color_initializer'
),
};
}

export function linearGradientLayer(gradient, project, extensionOptions) {
const { colorStops } = gradient;
const colorStopsPositionString = colorStops
.map((colorStop, index) => `${index}`)
.join(', ');

return linearGradientTemplate(
gradient,
colorStopsString(colorStops, project, extensionOptions),
colorStopsPositionString
colorStopsString(colorStops, project, extensionOptions)
);
}

Expand All @@ -75,7 +62,6 @@ export default {
generateColorExtension,
cgColorString,
generateFontExtension,
options,
linearGradientLayer,
radialGradientLayer,
};
76 changes: 34 additions & 42 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,76 +1,69 @@
import {
generateColorExtension,
cgColorString,
generateFontExtension,
options,
linearGradientLayer,
radialGradientLayer,
} from './helpers';
import zepcode from './zepcode';

function styleguideColors(context, colors) {
return generateColorExtension(colors, options(context));
return zepcode(context).generateColorExtension(colors);
}

function styleguideTextStyles(context, textStyles) {
return generateFontExtension(textStyles);
return zepcode(context).generateFontExtension(textStyles);
}

function layer(context, layerParams) {
const zepcodeInstance = zepcode(context);
let string = '';
const newlineBeforeContent = () => (string.length ? '\n\n' : '');

if (layerParams.fills.length) {
const { gradient } = layerParams.fills[0];
let gradientString = '';

if (gradient !== undefined) {
switch (gradient.type) {
case 'linear':
string += linearGradientLayer(
gradient,
context.project,
options(context)
);
gradientString = zepcodeInstance.linearGradientLayer(gradient);
break;
case 'radial':
string += radialGradientLayer(
gradient,
context.project,
options(context)
);
gradientString = zepcodeInstance.radialGradientLayer(gradient);
break;
default:
break;
}
}
string += gradientString;
}
if (string.length > 0) {
string += '\n\n';
}

if (layerParams.opacity !== 1) {
string += `view.alpha = ${layerParams.opacity.toFixed(2)}\n`;
string += `${newlineBeforeContent()}view.alpha = ${layerParams.opacity.toFixed(
2
)}\n`;
}
if (layerParams.borders.length > 0) {

if (layerParams.borders.length) {
const border = layerParams.borders[0];
string += `view.layer.borderWidth = ${border.thickness.toString()}\n`;
const { color } = border.fill;
string += `view.layer.borderWidth = ${border.thickness.toString()}\n`;

if (color !== undefined) {
const borderColorString = cgColorString(
border.fill.color,
context.project,
options(context)
const borderColorString = zepcodeInstance.cgColorString(
border.fill.color
);
string += `view.layer.borderColor = ${borderColorString}\n`;
}
}

if (layerParams.borderRadius > 0) {
string += `view.layer.cornerRadius = ${layerParams.borderRadius}`;
string += `${newlineBeforeContent()}view.layer.cornerRadius = ${
layerParams.borderRadius
}`;
}
if (layerParams.shadows.length > 0) {

if (layerParams.shadows.length) {
const shadow = layerParams.shadows[0];
const { color } = shadow;
if (color) {
const shadowColor = cgColorString(
shadow.color,
context.project,
options(context)
);
string += newlineBeforeContent();

if (color !== undefined) {
const shadowColor = zepcodeInstance.cgColorString(shadow.color);
string += `view.layer.shadowColor = ${shadowColor}\n`;
}
string += `view.layer.shadowOffset = `;
Expand All @@ -93,16 +86,15 @@ function layer(context, layerParams) {
}

function comment(context, text) {
const { textOption } = options(context);
return `${text} ${textOption !== undefined ? textOption : ''}`;
return zepcode(context).commentString(text);
}

function exportStyleguideColors(context, colors) {
return generateColorExtension(colors, options(context));
return zepcode(context).generateColorExtension(colors);
}

function exportStyleguideTextStyles(context, textStyles) {
return generateFontExtension(textStyles);
return zepcode(context).generateFontExtension(textStyles);
}

export default {
Expand Down
12 changes: 6 additions & 6 deletions src/templates/color-extension.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import customColorTemplate from './custom-color';
import colorTemplate from './color';

const colorExtensionTemplate = (colors, extensionOptions) =>`import UIKit
const colorExtensionTemplate = (colors, options) =>`import UIKit
extension UIColor {
${
extensionOptions.useCustomColorInitializer
? `\n convenience init(r red: Int, g green: Int, b blue: Int, a: CGFloat = 1) {
options.useCustomColorInitializer
? `\n convenience init(r red: Int, g green: Int, b blue: Int, a: CGFloat = 1) {
self.init(red: CGFloat(red) / 255, green: CGFloat(green) / 255, blue: CGFloat(blue) / 255, alpha: a)
}\n`
: ``}
${colors.map(color => `static let ${color.name} = ${
extensionOptions.useCustomColorInitializer
: ``}
${colors.map(color => `static let ${color.name} = ${
options.useCustomColorInitializer
? customColorTemplate(color)
: colorTemplate(color)
}`).join('\n ')}
Expand Down
102 changes: 87 additions & 15 deletions src/templates/linear-gradient.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,90 @@
const linearGradientTemplate = (
gradient,
colorStopsString,
colorStopsPositionString
) => `
let gradientLayer = CAGradientLayer()
gradientLayer.frame = view.bounds
${
gradient.angle === 90
? `gradientLayer.startPoint = CGPoint(x: 0.0, y: 0.5)
gradientLayer.endPoint = CGPoint(x: 1.0, y: 0.5)`
: ``
const linearGradientTemplate = (gradient, colorStopsString) =>
`import UIKit
final class LinearGradientLayer: CALayer {
enum Direction {
case vertical
case horizontal
case custom(start: CGPoint, end: CGPoint)
var points: (start: CGPoint, end: CGPoint) {
switch self {
case .vertical:
return (CGPoint(x: 0.5, y: 0.0), CGPoint(x: 0.5, y: 1.0))
case .horizontal:
return (CGPoint(x: 0.0, y: 0.5), CGPoint(x: 1.0, y: 0.5))
case let .custom(start, end):
return (start, end)
}
}
}
var direction: Direction = .vertical
var colorSpace = CGColorSpaceCreateDeviceRGB()
var colors: [CGColor]?
var locations: [CGFloat]?
var options: CGGradientDrawingOptions = CGGradientDrawingOptions(rawValue: 0)
required override init() {
super.init()
masksToBounds = true
needsDisplayOnBoundsChange = true
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
required override init(layer: Any) {
super.init(layer: layer)
}
override func draw(in ctx: CGContext) {
ctx.saveGState()
guard let colors = colors, let gradient = CGGradient(colorsSpace: colorSpace,
colors: colors as CFArray, locations: locations) else { return }
let points = direction.points
ctx.drawLinearGradient(
gradient,
start: transform(points.start),
end: transform(points.end),
options: options
)
}
private func transform(_ point: CGPoint) -> CGPoint {
return CGPoint(x: bounds.width * point.x, y: bounds.height * point.y)
}
}
gradientLayer.colors = [${colorStopsString}]
gradientLayer.locations = [${colorStopsPositionString}]
view.layer.insertSublayer(gradientLayer, at: 0)`;
final class GradientView: UIView {
lazy var gradientLayer: LinearGradientLayer = {
let gradientLayer = LinearGradientLayer()
gradientLayer.colors = [${colorStopsString}]
return gradientLayer
}()
override init(frame: CGRect) {
super.init(frame: frame)
layer.insertSublayer(gradientLayer, at: 0)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
layer.insertSublayer(gradientLayer, at: 0)
}
override func layoutSubviews() {
super.layoutSubviews()
gradientLayer.frame = bounds
}
}`;

export default linearGradientTemplate;
86 changes: 86 additions & 0 deletions src/zepcode.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import colorExtensionTemplate from './templates/color-extension';
import customColorTemplate from './templates/custom-color';
import colorTemplate from './templates/color';
import linearGradientTemplate from './templates/linear-gradient';
import radialGradientTemplate from './templates/radial-gradient';
import fontExtensionTemplate from './templates/font-extension';

const zepcode = (() => {
let instance;

function init(privateContext) {
let me;
if (privateContext !== undefined) {
me = {
options: {
useColorNames: privateContext.getOption('use_color_names'),
useCustomColorInitializer: privateContext.getOption(
'use_custom_color_initializer'
),
},
project: privateContext.project,
};
}

me.cgColorString = color => {
const styleguideColor = me.project.findColorEqual(color);
const cgColorPostfix = '.cgColor';

if (me.options.useColorNames && styleguideColor) {
return `UIColor.${styleguideColor.name}${cgColorPostfix}`;
}
if (me.options.useCustomColorInitializer) {
return customColorTemplate(color) + cgColorPostfix;
}
return colorTemplate(color) + cgColorPostfix;
};

me.colorStopsString = gradient => {
const { colorStops } = gradient;
return colorStops
.map(colorStop => me.cgColorString(colorStop.color))
.join(', ');
};

me.linearGradientLayer = gradient =>
linearGradientTemplate(gradient, me.colorStopsString(gradient));

me.radialGradientLayer = gradient =>
radialGradientTemplate(me.colorStopsString(gradient));

me.commentString = text => {
const { textOption } = me.options;
return `${text} ${textOption !== undefined ? textOption : ''}`;
};

me.generateColorExtension = colors => ({
code: colorExtensionTemplate(colors, me.options),
language: 'swift',
filename: 'UIColor+AppColors.swift',
});

me.generateFontExtension = textStyles => {
const uniqueFonts = Array.from(
new Set(textStyles.map(style => style.fontFace))
).sort();

return {
code: fontExtensionTemplate(uniqueFonts),
language: 'swift',
filename: 'UIFont+AppFonts.swift',
};
};

return me;
}

return context => {
if (!instance) {
instance = init(context);
}

return instance;
};
})();

export default zepcode;

0 comments on commit 19bb345

Please sign in to comment.