admiral-tools-figma 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +1 -0
  3. data/admiral-tools-figma.gemspec +9 -0
  4. data/admiraltools/actions/figma_download_images.rb +116 -0
  5. data/admiraltools/actions/figma_generate_styles.rb +77 -0
  6. data/admiraltools/actions/figma_get_image_links.rb +139 -0
  7. data/admiraltools/actions/figma_get_styles.rb +90 -0
  8. data/admiraltools/helper/admiraltools_helper.rb +18 -0
  9. data/admiraltools/helper/figma/figma_client/figma_client.rb +193 -0
  10. data/admiraltools/helper/figma/figma_client/models/api/primitives/figma_color.rb +35 -0
  11. data/admiraltools/helper/figma/figma_client/models/api/primitives/figma_component.rb +58 -0
  12. data/admiraltools/helper/figma/figma_client/models/api/primitives/figma_components_styles_meta.rb +30 -0
  13. data/admiraltools/helper/figma/figma_client/models/api/primitives/figma_frame_info.rb +46 -0
  14. data/admiraltools/helper/figma/figma_client/models/api/primitives/figma_node.rb +43 -0
  15. data/admiraltools/helper/figma/figma_client/models/api/primitives/figma_paint.rb +32 -0
  16. data/admiraltools/helper/figma/figma_client/models/api/primitives/figma_style.rb +48 -0
  17. data/admiraltools/helper/figma/figma_client/models/api/primitives/figma_type_style.rb +56 -0
  18. data/admiraltools/helper/figma/figma_client/models/api/results/figma_components_styles_result.rb +36 -0
  19. data/admiraltools/helper/figma/figma_client/models/api/results/figma_images_result.rb +25 -0
  20. data/admiraltools/helper/figma/figma_client/models/api/results/figma_nodes_result.rb +52 -0
  21. data/admiraltools/helper/figma/figma_client/models/domain/converters/figma_to_domain_converter.rb +98 -0
  22. data/admiraltools/helper/figma/figma_client/models/domain/primitives/color.rb +44 -0
  23. data/admiraltools/helper/figma/figma_client/models/domain/primitives/component.rb +86 -0
  24. data/admiraltools/helper/figma/figma_client/models/domain/primitives/components_list.rb +29 -0
  25. data/admiraltools/helper/figma/figma_client/models/domain/primitives/font.rb +56 -0
  26. data/admiraltools/helper/figma/figma_client/models/domain/primitives/frame_info.rb +46 -0
  27. data/admiraltools/helper/figma/figma_client/models/domain/primitives/image_link.rb +33 -0
  28. data/admiraltools/helper/figma/figma_client/models/domain/primitives/style.rb +113 -0
  29. data/admiraltools/helper/figma/figma_client/models/domain/primitives/styles_group.rb +22 -0
  30. data/admiraltools/helper/figma/figma_client/models/domain/primitives/styles_list.rb +29 -0
  31. data/admiraltools/helper/figma/figma_client/models/models.rb +25 -0
  32. data/admiraltools/helper/figma/figma_image_downloader/bin/svg2vectordrawable.jar +0 -0
  33. data/admiraltools/helper/figma/figma_image_downloader/figma_image_downloader.rb +65 -0
  34. data/admiraltools/helper/figma/figma_image_downloader/generators/folder_generator.rb +47 -0
  35. data/admiraltools/helper/figma/figma_image_downloader/generators/folder_generator_raw.rb +32 -0
  36. data/admiraltools/helper/figma/figma_image_downloader/generators/folder_generator_res.rb +38 -0
  37. data/admiraltools/helper/figma/figma_image_downloader/generators/folder_generator_xcassets.rb +180 -0
  38. data/admiraltools/helper/figma/figma_image_downloader/generators/generators.rb +6 -0
  39. data/admiraltools/helper/figma/figma_image_downloader/helpers/image_name_formatter.rb +72 -0
  40. data/admiraltools/helper/figma/figma_image_downloader/helpers/progress_tasks_logger.rb +22 -0
  41. data/admiraltools/helper/figma/figma_image_downloader/helpers/scale_formatter.rb +96 -0
  42. data/admiraltools/helper/figma/figma_image_downloader/helpers/svg_to_vector_converter.rb +12 -0
  43. data/admiraltools/helper/figma/figma_image_downloader/models/download_image_params.rb +31 -0
  44. data/admiraltools/helper/figma/figma_image_downloader/models/image_name_components.rb +10 -0
  45. data/admiraltools/helper/figma/figma_image_downloader/models/image_ref.rb +12 -0
  46. data/admiraltools/helper/figma/figma_image_downloader/models/image_set_ref.rb +14 -0
  47. data/admiraltools/helper/figma/figma_image_downloader/models/models.rb +5 -0
  48. data/admiraltools/helper/figma/figma_template_generator/figma_template_generator.rb +22 -0
  49. data/admiraltools/helper/figma/figma_template_generator/models/styles_template.rb +34 -0
  50. data/admiraltools/helper/figma/helpers/file_folder.rb +30 -0
  51. data/admiraltools/helper/figma/helpers/hash_access.rb +18 -0
  52. data/admiraltools/helper/figma/helpers/string_filters.rb +63 -0
  53. data/admiraltools/helper/figma/helpers/string_format.rb +60 -0
  54. data/admiraltools/helper/system/system.rb +17 -0
  55. data/admiraltools/version.rb +7 -0
  56. data/admiraltools.rb +18 -0
  57. metadata +96 -0
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Font
4
+ attr_accessor \
5
+ :font_family,
6
+ :font_postscript_name,
7
+ :font_size,
8
+ :font_weight,
9
+ :letter_spacing
10
+
11
+ def initialize(
12
+ font_family:,
13
+ font_postscript_name:,
14
+ font_size:,
15
+ font_weight:,
16
+ letter_spacing:
17
+ )
18
+ @font_family = font_family
19
+ @font_postscript_name = font_postscript_name
20
+ @font_size = font_size
21
+ @font_weight = font_weight
22
+ @letter_spacing = letter_spacing
23
+ end
24
+
25
+ def self.from_hash(hash)
26
+ return nil if hash.nil?
27
+
28
+ font_family = hash['font_family']
29
+ font_postscript_name = hash['font_postscript_name']
30
+ font_size = hash['font_size']
31
+ font_weight = hash['font_weight']
32
+ letter_spacing = hash['letter_spacing']
33
+
34
+ if !font_family.nil? && !font_postscript_name.nil? && !font_size.nil? && !font_weight.nil? && !letter_spacing.nil?
35
+ return Font.new(
36
+ font_family: font_family,
37
+ font_postscript_name: font_postscript_name,
38
+ font_size: font_size,
39
+ font_weight: font_weight,
40
+ letter_spacing: letter_spacing
41
+ )
42
+ end
43
+
44
+ nil
45
+ end
46
+
47
+ def to_hash
48
+ hash = {}
49
+ hash['font_family'] = font_family
50
+ hash['font_postscript_name'] = font_postscript_name
51
+ hash['font_size'] = font_size
52
+ hash['font_weight'] = font_weight
53
+ hash['letter_spacing'] = letter_spacing
54
+ hash
55
+ end
56
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ class FrameInfo
4
+ attr_accessor \
5
+ :node_id,
6
+ :name,
7
+ :background_color,
8
+ :page_id,
9
+ :page_name
10
+
11
+ def initialize(
12
+ node_id:,
13
+ name:,
14
+ background_color:,
15
+ page_id:,
16
+ page_name:
17
+ )
18
+ @node_id = node_id
19
+ @name = name
20
+ @background_color = background_color
21
+ @page_id = page_id
22
+ @page_name = page_name
23
+ end
24
+
25
+ def self.from_hash(hash)
26
+ return nil if hash.nil?
27
+
28
+ node_id = hash['node_id']
29
+ name = hash['name']
30
+ background_color = hash['background_color']
31
+ page_id = hash['page_id']
32
+ page_name = hash['page_name']
33
+ FigmaFrameInfo.new(node_id: node_id, name: name, background_color: background_color, page_id: page_id,
34
+ page_name: page_name)
35
+ end
36
+
37
+ def to_hash
38
+ hash = {}
39
+ hash['node_id'] = node_id
40
+ hash['name'] = name
41
+ hash['background_color'] = background_color
42
+ hash['page_id'] = page_id
43
+ hash['page_name'] = page_name
44
+ hash
45
+ end
46
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ImageLink
4
+ attr_accessor :link, :scale, :image_format
5
+
6
+ def initialize(link:, scale:, image_format:)
7
+ @link = link
8
+ @scale = scale
9
+ @image_format = image_format
10
+ end
11
+
12
+ def self.from_hash(hash)
13
+ return nil if hash.nil?
14
+
15
+ scale = hash['scale']
16
+ link = hash['link']
17
+ image_format = hash['image_format']
18
+
19
+ if !scale.nil? && !link.nil? && !image_format.nil?
20
+ return ImageLink.new(scale: scale, link: link, image_format: image_format)
21
+ end
22
+
23
+ nil
24
+ end
25
+
26
+ def to_hash
27
+ hash = {}
28
+ hash['scale'] = scale
29
+ hash['link'] = link
30
+ hash['image_format'] = image_format
31
+ hash
32
+ end
33
+ end
@@ -0,0 +1,113 @@
1
+ # frozen_string_literal: true
2
+
3
+ class StyleNameInfo
4
+ attr_accessor :full_name, :group_name, :style_name
5
+
6
+ def initialize(
7
+ full_name:,
8
+ group_name:,
9
+ style_name:
10
+ )
11
+ @full_name = full_name
12
+ @group_name = group_name
13
+ @style_name = style_name
14
+ end
15
+
16
+ def self.create_from(name:)
17
+ name ||= ''
18
+ full_name = name
19
+ name_array = name.split('/')
20
+
21
+ if name_array.count > 1
22
+ group_name = name_array[0]
23
+ name_array.shift
24
+ style_name = name_array.join('/')
25
+ else
26
+ group_name = 'Default'
27
+ style_name = name_array[0] || 'unknown'
28
+ end
29
+
30
+ StyleNameInfo.new(
31
+ full_name: full_name,
32
+ group_name: group_name,
33
+ style_name: style_name
34
+ )
35
+ end
36
+
37
+ def to_hash
38
+ hash = {}
39
+ hash['full_name'] = full_name
40
+ hash['group_name'] = group_name
41
+ hash['style_name'] = style_name
42
+ hash
43
+ end
44
+ end
45
+
46
+ class Style
47
+ attr_accessor :name, :node_id, :style_type, :description, :color, :font
48
+
49
+ def description_params
50
+ JSON.parse(description)
51
+ rescue StandardError
52
+ nil
53
+ end
54
+
55
+ def initialize(
56
+ name:,
57
+ node_id:,
58
+ style_type:,
59
+ description:,
60
+ color: nil,
61
+ font: nil
62
+ )
63
+ @name = name
64
+ @node_id = node_id
65
+ @style_type = style_type
66
+ @description = description
67
+ @color = color
68
+ @font = font
69
+ end
70
+
71
+ def name_info
72
+ StyleNameInfo.create_from(name: name)
73
+ end
74
+
75
+ def is_dark
76
+ name.downcase.include?('dark') || false
77
+ end
78
+
79
+ def self.from_hash(hash)
80
+ return nil if hash.nil?
81
+
82
+ name = hash['name']
83
+ node_id = hash['node_id']
84
+ style_type = hash['style_type']
85
+ description = hash['description']
86
+ color_hash = hash['color']
87
+ font_hash = hash['font']
88
+
89
+ color = !color_hash.nil? ? Color.from_hash(color_hash) : nil
90
+ font = !font_hash.nil? ? Font.from_hash(font_hash) : nil
91
+
92
+ if !name.nil? && !node_id.nil? && style_type
93
+ return Style.new(name: name, node_id: node_id, style_type: style_type, description: description,
94
+ color: color, font: font)
95
+ end
96
+
97
+ nil
98
+ end
99
+
100
+ def to_hash
101
+ hash = {}
102
+ hash['name'] = name
103
+ hash['node_id'] = node_id
104
+ hash['style_type'] = style_type
105
+ hash['description'] = description
106
+ hash['color'] = color&.to_hash unless color.nil?
107
+ hash['font'] = font&.to_hash unless font.nil?
108
+ hash['name_info'] = name_info.to_hash unless name_info.nil?
109
+ hash['description_params'] = description_params unless description_params.nil?
110
+ hash['is_dark'] = is_dark
111
+ hash
112
+ end
113
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ class StylesGroup
4
+ attr_accessor :name, :styles
5
+
6
+ def initialize(name:, styles:)
7
+ @name = name
8
+ @styles = styles
9
+ end
10
+
11
+ def is_dark
12
+ name.downcase.include?('dark') || false
13
+ end
14
+
15
+ def to_hash
16
+ hash = {}
17
+ hash['name'] = name
18
+ hash['styles'] = styles&.map { |s| s.to_hash }
19
+ hash['is_dark'] = is_dark
20
+ hash
21
+ end
22
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+ require_relative 'style'
5
+
6
+ class StylesList
7
+ attr_accessor :styles
8
+
9
+ def initialize(styles:)
10
+ @styles = styles
11
+ end
12
+
13
+ def self.from_hash(hash)
14
+ hash.map { |s| Style.from_hash(s) }
15
+ end
16
+
17
+ def to_hash
18
+ styles.map(&:to_hash)
19
+ end
20
+
21
+ def self.from_json(json)
22
+ styles = (JSON.parse(json) || []).map { |s| Style.from_hash(s) }
23
+ StylesList.new(styles: styles)
24
+ end
25
+
26
+ def to_json(*_args)
27
+ styles.map(&:to_hash).to_json
28
+ end
29
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'api/primitives/figma_color'
4
+ require_relative 'api/primitives/figma_component'
5
+ require_relative 'api/primitives/figma_components_styles_meta'
6
+ require_relative 'api/primitives/figma_node'
7
+ require_relative 'api/primitives/figma_paint'
8
+ require_relative 'api/primitives/figma_style'
9
+ require_relative 'api/primitives/figma_type_style'
10
+ require_relative 'api/primitives/figma_color'
11
+
12
+ require_relative 'api/results/figma_components_styles_result'
13
+ require_relative 'api/results/figma_images_result'
14
+ require_relative 'api/results/figma_nodes_result'
15
+
16
+ require_relative 'domain/primitives/color'
17
+ require_relative 'domain/primitives/component'
18
+ require_relative 'domain/primitives/components_list'
19
+ require_relative 'domain/primitives/font'
20
+ require_relative 'domain/primitives/image_link'
21
+ require_relative 'domain/primitives/style'
22
+ require_relative 'domain/primitives/styles_group'
23
+ require_relative 'domain/primitives/styles_list'
24
+
25
+ require_relative 'domain/converters/figma_to_domain_converter'
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'models/models'
4
+ require_relative 'generators/generators'
5
+ require_relative 'helpers/progress_tasks_logger'
6
+
7
+ class FigmaImageDownloader
8
+ OUTPUT_FORMAT_RAW = 'raw'
9
+ OUTPUT_FORMAT_RES = 'res'
10
+ OUTPUT_FORMAT_XCASSETS = 'xcassets'
11
+ OUTPUT_FORMAT_XCASSETS_SYMOBLS = 'xcassets-symbols'
12
+
13
+ XCASSETS_TEMPLATE_RENDERING_INTENT_ORIGINAL = 'original'
14
+ XCASSETS_TEMPLATE_RENDERING_INTENT_TEMPLATE = 'template'
15
+
16
+ def download_images(params:)
17
+ generator = generator(params: params)
18
+
19
+ image_set_refs = params.image_components.map { |c| generator.create_image_sets(image_component: c) }
20
+ total_count = image_set_refs.map(&:image_refs).flatten.length
21
+
22
+ logger = ProgressTasksLogger.new(total_count: total_count)
23
+ puts("Start downloading #{total_count}")
24
+ generator.start_download(image_sets: image_set_refs)
25
+ image_set_refs.each do |image_set|
26
+ puts("Image set: #{image_set.name}")
27
+ generator.image_set_start_download(image_set: image_set)
28
+ image_set.image_refs.each do |image|
29
+ generator.image_start_download(image: image)
30
+ download_task(task: image, output_folder: params.output_folder)
31
+ logger.increment
32
+ puts("#{logger.progress_string} #{image.path} #{image.image_link.link}")
33
+ generator.image_end_download(image: image)
34
+ end
35
+ generator.image_set_end_download(image_set: image_set)
36
+ end
37
+ puts("\nDownloading complete! #{logger.progress_string}")
38
+ generator.end_download(image_sets: image_set_refs)
39
+ end
40
+
41
+ private
42
+
43
+ def generator(params:)
44
+ case params.output_format
45
+ when OUTPUT_FORMAT_RAW
46
+ FolderGeneratorRaw.new(params: params)
47
+ when OUTPUT_FORMAT_RES
48
+ FolderGeneratorRes.new(params: params)
49
+ when OUTPUT_FORMAT_XCASSETS
50
+ FolderGeneratorXcassets.new(params: params, symbols: false)
51
+ when OUTPUT_FORMAT_XCASSETS_SYMOBLS
52
+ FolderGeneratorXcassets.new(params: params, symbols: true)
53
+ else
54
+ raise 'Unknown output format'
55
+ end
56
+ end
57
+
58
+ def download_task(task:, output_folder:)
59
+ data = open(task.image_link.link)
60
+ path = File.join(output_folder, task.path)
61
+ file = File.open_file(file_name: path, mode: 'w', create_directories: true)
62
+ file.write(data.read)
63
+ file.close
64
+ end
65
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ class FolderGenerator
4
+ attr_accessor :params
5
+
6
+ def initialize(params:)
7
+ @params = params
8
+ end
9
+
10
+ def start_download(image_sets:); end
11
+
12
+ def end_download(image_sets:); end
13
+
14
+ def create_image_sets(image_component:); end
15
+
16
+ def image_set_start_download(image_set:); end
17
+
18
+ def image_set_end_download(image_set:); end
19
+
20
+ def image_start_download(image:); end
21
+
22
+ def image_end_download(image:); end
23
+
24
+ def format_name(image_component:)
25
+ formatter = ImageNameFormatter.new
26
+ page_name = params.include_page_name ? image_component.containing_frame.page_name : nil
27
+ frame_name = params.include_frame_name ? image_component.containing_frame.name : nil
28
+
29
+ formatter.separate(
30
+ name: image_component.name,
31
+ page_name: page_name,
32
+ frame_name: frame_name,
33
+ naming_style: params.naming_style,
34
+ folder_depth: params.folder_depth
35
+ )
36
+ end
37
+
38
+ def image_path(group_name:, image_link:, single_scale:)
39
+ formatter = ImageNameFormatter.new
40
+ formatter.image_path(
41
+ group_name: group_name,
42
+ image_link: image_link,
43
+ single_scale: single_scale,
44
+ convert_to_dpi: params.convert_scales_to_dpi
45
+ )
46
+ end
47
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'folder_generator'
4
+ require_relative '../helpers/scale_formatter'
5
+ require_relative '../helpers/image_name_formatter'
6
+ require_relative '../models/image_set_ref'
7
+
8
+ class FolderGeneratorRaw < FolderGenerator
9
+ def create_image_sets(image_component:)
10
+ name_components = format_name(image_component: image_component)
11
+ name = name_components.name
12
+ folder = name_components.folder
13
+
14
+ image_links = image_component.image_links
15
+ single_scale = image_component.single_scale?
16
+
17
+ image_refs = image_links.map do |i|
18
+ file_name = image_path(group_name: name, image_link: i, single_scale: single_scale)
19
+ item_path = File.join(folder, file_name)
20
+ ImageRef.new(path: item_path, image_link: i)
21
+ end
22
+
23
+ ImageSetRef.new(name: name, folder: folder, image_refs: image_refs, single_scale: single_scale)
24
+ end
25
+
26
+ def image_end_download(image:)
27
+ return unless params.convert_svg_to_vector
28
+
29
+ input_file = File.join(params.output_folder, image.path)
30
+ SvtToVectorConverter.new.convert(input_file: input_file)
31
+ end
32
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'folder_generator'
4
+ require_relative '../helpers/scale_formatter'
5
+ require_relative '../helpers/image_name_formatter'
6
+ require_relative '../models/image_set_ref'
7
+
8
+ class FolderGeneratorRes < FolderGenerator
9
+ def create_image_sets(image_component:)
10
+ name_components = format_name(image_component: image_component)
11
+ name = name_components.name
12
+ folder = name_components.folder
13
+
14
+ image_links = image_component.image_links
15
+ single_scale = image_component.single_scale?
16
+
17
+ image_refs = image_links.map do |i|
18
+ file_name = "#{name}.#{i.image_format}"
19
+ scale_folder = folder_for_scale(scale: i.scale, single_scale: single_scale)
20
+ item_path = File.join(folder, scale_folder, file_name)
21
+ ImageRef.new(path: item_path, image_link: i)
22
+ end
23
+
24
+ ImageSetRef.new(name: name, folder: folder, image_refs: image_refs, single_scale: single_scale)
25
+ end
26
+
27
+ def folder_for_scale(scale:, single_scale:)
28
+ dpi = ScaleFormatter.new.dpi_from_scale(scale)
29
+ !single_scale && !dpi.nil? ? "drawable-#{dpi}" : 'drawable'
30
+ end
31
+
32
+ def image_end_download(image:)
33
+ return unless params.convert_svg_to_vector
34
+
35
+ input_file = File.join(params.output_folder, image.path)
36
+ SvtToVectorConverter.new.convert(input_file: input_file)
37
+ end
38
+ end
@@ -0,0 +1,180 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+ require_relative 'folder_generator'
5
+ require_relative '../../helpers/hash_access'
6
+ require_relative '../helpers/scale_formatter'
7
+ require_relative '../helpers/image_name_formatter'
8
+ require_relative '../models/image_set_ref'
9
+
10
+ class FolderGeneratorXcassets < FolderGenerator
11
+
12
+ attr_accessor :symbols
13
+
14
+ def initialize(symbols:, params:)
15
+ @symbols = symbols
16
+ super(params: params)
17
+ end
18
+
19
+ def start_download(image_sets:)
20
+ create_root_content_json(folder: params.output_folder)
21
+ end
22
+
23
+ def image_set_start_download(image_set:)
24
+ create_recursive_asset_contnet_json(folder: image_set.folder)
25
+
26
+ if symbols
27
+ create_symbolset_content_json(image_set: image_set)
28
+ else
29
+ create_imageset_content_json(image_set: image_set)
30
+ end
31
+ end
32
+
33
+ def image_end_download(image:)
34
+ return unless params.convert_svg_to_vector
35
+
36
+ input_file = File.join(params.output_folder, image.path)
37
+ SvtToVectorConverter.new.convert(input_file: input_file)
38
+ end
39
+
40
+ def create_image_sets(image_component:)
41
+ name_components = format_name(image_component: image_component)
42
+ name = name_components.name
43
+ extension = symbols ? 'symbolset' : 'imageset'
44
+ folder = File.join(name_components.folder, "#{name}.#{extension}")
45
+
46
+ image_links = image_component.image_links
47
+ single_scale = image_component.single_scale?
48
+
49
+ image_refs = image_links.map do |i|
50
+ file_name = image_path(group_name: name, image_link: i, single_scale: single_scale)
51
+ item_path = File.join(folder, file_name)
52
+ ImageRef.new(path: item_path, image_link: i)
53
+ end
54
+
55
+ ImageSetRef.new(name: name, folder: folder, image_refs: image_refs, single_scale: single_scale)
56
+ end
57
+
58
+ private
59
+
60
+ def create_root_content_json(folder:)
61
+ file_path = File.join(folder, 'Contents.json')
62
+ return if File.exist?(file_path)
63
+
64
+ content = content_template
65
+ File.write_file_json(path: file_path, hash: content)
66
+ end
67
+
68
+ def create_recursive_asset_contnet_json(folder:)
69
+ folder_root = params.output_folder
70
+
71
+ folders = folder.split('/')[0...-1].map do |f|
72
+ folder_root = File.join(folder_root, f)
73
+ folder_root
74
+ end
75
+
76
+ folders.each { |f| create_asset_contnet_json(folder: f) }
77
+ end
78
+
79
+ def add_content_property(content:, key:, value:)
80
+ if content.dig('properties', key).nil? && !value.nil?
81
+ properties = content['properties'] || {}
82
+ properties[key] = value
83
+ content['properties'] = properties
84
+ end
85
+ end
86
+
87
+ def create_asset_contnet_json(folder:)
88
+ file_path = File.join(folder, 'Contents.json')
89
+ content = File.read_file_json(path: file_path) || content_template
90
+ xcassets_params = params.xcassets_params || {}
91
+ provides_namespace = xcassets_params[:provides_namespace]
92
+
93
+ add_content_property(content: content, key: 'provides-namespace', value: provides_namespace)
94
+
95
+ File.write_file_json(path: file_path, hash: content)
96
+ end
97
+
98
+ def content_template
99
+ content = {}
100
+ content['info'] = {}
101
+ content['info']['version'] = 1
102
+ content['info']['author'] = 'xcode'
103
+ content
104
+ end
105
+
106
+ def create_symbolset_content_json(image_set:)
107
+ image_refs = image_set&.image_refs || []
108
+
109
+ if image_refs.empty?
110
+ return
111
+ end
112
+
113
+ folder = File.join(params.output_folder, image_set.folder)
114
+ file_path = File.join(folder, 'Contents.json')
115
+ content = File.read_file_json(path: file_path) || content_template
116
+ symbols = content['symbols'] || []
117
+
118
+ ref = image_refs[0]
119
+ filename = File.basename(ref.path)
120
+
121
+ symbol = symbols.first || {}
122
+ symbol['filename'] = filename
123
+ symbol['idiom'] = 'universal' if symbol['idiom'].nil?
124
+
125
+ symbols = [symbol]
126
+ content['symbols'] = symbols
127
+
128
+ xcassets_params = params.xcassets_params || {}
129
+ language_direction = xcassets_params[:language_direction]
130
+ add_content_property(content: content, key: 'language-direction', value: language_direction)
131
+
132
+ File.write_file_json(path: file_path, hash: content)
133
+ end
134
+
135
+ def create_imageset_content_json(image_set:)
136
+ folder = File.join(params.output_folder, image_set.folder)
137
+ file_path = File.join(folder, 'Contents.json')
138
+ content = File.read_file_json(path: file_path) || content_template
139
+ images = content['images'] || []
140
+
141
+ image_set&.image_refs&.each do |task|
142
+ filename = File.basename(task.path)
143
+ image_names = images.map { |i| i['filename'] }.compact
144
+ image_index = image_names.find_index(filename)
145
+
146
+ if image_index.nil?
147
+ images.push({})
148
+ image_index = images.length - 1
149
+ end
150
+
151
+ image = images[image_index]
152
+
153
+ image['filename'] = filename
154
+ image['idiom'] = 'universal' if image['idiom'].nil?
155
+
156
+ scale = task.image_link.scale
157
+ scale_enabled = !scale.nil? && !image_set.single_scale
158
+
159
+ if scale_enabled
160
+ image['scale'] = ScaleFormatter.new.formatted_scale(scale: scale)
161
+ else
162
+ image.delete('scale')
163
+ end
164
+ end
165
+
166
+ content['images'] = images
167
+ xcassets_params = params.xcassets_params || {}
168
+ template_rendering_intent = xcassets_params[:template_rendering_intent]
169
+ preserves_vector_representation = xcassets_params[:preserves_vector_representation]
170
+
171
+ add_content_property(content: content, key: 'template-rendering-intent', value: template_rendering_intent)
172
+ add_content_property(content: content, key: 'preserves-vector-representation', value: preserves_vector_representation)
173
+
174
+ File.write_file_json(path: file_path, hash: content)
175
+ end
176
+
177
+ end
178
+
179
+
180
+