admiral-tools-figma 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+