solara 0.4.0 → 0.6.0

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 (60) hide show
  1. checksums.yaml +4 -4
  2. data/solara/lib/.DS_Store +0 -0
  3. data/solara/lib/core/.DS_Store +0 -0
  4. data/solara/lib/core/brands/brand_onboarder.rb +1 -1
  5. data/solara/lib/core/brands/brand_switcher.rb +92 -1
  6. data/solara/lib/core/dashboard/brand/BrandDetail.js +34 -2
  7. data/solara/lib/core/dashboard/brand/BrandDetailController.js +27 -234
  8. data/solara/lib/core/dashboard/brand/BrandDetailModel.js +14 -5
  9. data/solara/lib/core/dashboard/brand/BrandDetailView.js +16 -200
  10. data/solara/lib/core/dashboard/brand/SectionsFormManager.js +293 -0
  11. data/solara/lib/core/dashboard/brand/brand.html +223 -174
  12. data/solara/lib/core/dashboard/brand/source/BrandLocalSource.js +2 -5
  13. data/solara/lib/core/dashboard/brand/source/BrandRemoteSource.js +36 -133
  14. data/solara/lib/core/dashboard/brands/Brands.js +31 -0
  15. data/solara/lib/core/dashboard/brands/BrandsController.js +0 -5
  16. data/solara/lib/core/dashboard/brands/BrandsView.js +2 -2
  17. data/solara/lib/core/dashboard/brands/brands.html +71 -52
  18. data/solara/lib/core/dashboard/component/AliasesBottomSheet.js +6 -6
  19. data/solara/lib/core/dashboard/component/BrandOptionsBottomSheet.js +4 -4
  20. data/solara/lib/core/dashboard/component/ConfirmationDialog.js +15 -10
  21. data/solara/lib/core/dashboard/component/EditJsonSheet.js +160 -0
  22. data/solara/lib/core/dashboard/component/MessageBottomSheet.js +5 -5
  23. data/solara/lib/core/dashboard/component/OnboardBrandBottomSheet.js +9 -3
  24. data/solara/lib/core/dashboard/handler/base_handler.rb +1 -0
  25. data/solara/lib/core/dashboard/handler/edit_section_handler.rb +1 -5
  26. data/solara/lib/core/dashboard/handler/onboard_brand_handler.rb +0 -15
  27. data/solara/lib/core/doctor/schema/brand_configurations.json +0 -8
  28. data/solara/lib/core/doctor/schema/platform/global/resources_manifest.json +30 -0
  29. data/solara/lib/core/doctor/schema/platform/json_manifest.json +39 -0
  30. data/solara/lib/core/doctor/validator/template/android_template_validation_config.yml +35 -1
  31. data/solara/lib/core/doctor/validator/template/flutter_template_validation_config.yml +30 -1
  32. data/solara/lib/core/doctor/validator/template/ios_template_validation_config.yml +35 -1
  33. data/solara/lib/core/doctor/validator/template/template_validator.rb +9 -9
  34. data/solara/lib/core/scripts/brand_config_manager.rb +1 -1
  35. data/solara/lib/core/scripts/brand_configurations_manager.rb +41 -0
  36. data/solara/lib/core/scripts/code_generator.rb +342 -118
  37. data/solara/lib/core/scripts/file_manager.rb +11 -15
  38. data/solara/lib/core/scripts/file_path.rb +21 -1
  39. data/solara/lib/core/scripts/gitignore_manager.rb +12 -6
  40. data/solara/lib/core/scripts/json_manifest_processor.rb +136 -0
  41. data/solara/lib/core/scripts/platform/ios/infoplist_string_catalog_manager.rb +11 -1
  42. data/solara/lib/core/scripts/resource_manifest_processor.rb +151 -0
  43. data/solara/lib/core/scripts/solara_status_manager.rb +1 -1
  44. data/solara/lib/core/scripts/theme_generator.rb +21 -242
  45. data/solara/lib/core/solara_configurator.rb +1 -1
  46. data/solara/lib/core/template/brands/global/resources_manifest.json +10 -0
  47. data/solara/lib/core/template/brands/json/Json-Manifest.md +59 -0
  48. data/solara/lib/core/template/brands/json/json_manifest.json +16 -0
  49. data/solara/lib/core/template/brands/shared/theme.json +213 -29
  50. data/solara/lib/core/template/config/android_template_config.json +50 -0
  51. data/solara/lib/core/template/config/flutter_template_config.json +35 -0
  52. data/solara/lib/core/template/config/ios_template_config.json +50 -0
  53. data/solara/lib/core/template/configurations.json +46 -0
  54. data/solara/lib/core/template/project_template_generator.rb +2 -0
  55. data/solara/lib/solara/version.rb +1 -1
  56. data/solara/lib/solara.rb +19 -0
  57. data/solara/lib/solara_manager.rb +21 -13
  58. metadata +13 -4
  59. data/solara/lib/core/dashboard/component/AddFieldSheet.js +0 -175
  60. data/solara/lib/core/dashboard/handler/brand_configurations_manager.rb +0 -73
@@ -7,25 +7,29 @@ class ConfirmationDialog extends HTMLElement {
7
7
 
8
8
  render() {
9
9
  this.shadowRoot.innerHTML = `
10
- <style>
10
+ <style>
11
+ .title {
12
+ color: var(--text-color);
13
+ font-size: 14px;
14
+ }
11
15
  .confirmation-dialog {
12
16
  display: none;
13
17
  position: fixed;
14
18
  top: 50%;
15
19
  left: 50%;
16
20
  transform: translate(-50%, -50%);
17
- background-color: white;
18
- padding: 14px;
21
+ background-color: var(--background-color);
19
22
  border-radius: 7px;
20
23
  box-shadow: 0 2.8px 4.2px rgba(0, 0, 0, 0.1);
21
24
  z-index: 1001;
22
25
  text-align: center;
23
- font-size: 11.2px;
26
+ font-size: 11px;
27
+ padding: 20px;
24
28
  }
25
29
  .confirmation-dialog h3 {
26
30
  margin-top: 0;
27
31
  color: var(--primary-color);
28
- font-size: 15.4px;
32
+ font-size: 15px;
29
33
  }
30
34
  .confirmation-dialog .buttons {
31
35
  margin-top: 14px;
@@ -42,16 +46,18 @@ class ConfirmationDialog extends HTMLElement {
42
46
  .confirmation-dialog .confirm {
43
47
  background-color: #dc3545;
44
48
  color: white;
49
+ margin-top: 10px;
45
50
  }
46
51
  .confirmation-dialog .cancel {
47
52
  background-color: #ccc;
48
53
  color: #333;
49
- }
54
+ margin-top: 10px;
55
+ }
50
56
  .confirmation-dialog .confirm:hover {
51
- background-color: #c82333;
57
+ background-color: var(--hover);
52
58
  }
53
59
  .confirmation-dialog .cancel:hover {
54
- background-color: #bbb;
60
+ background-color: var(--hover);
55
61
  }
56
62
  .overlay {
57
63
  display: none;
@@ -66,8 +72,7 @@ class ConfirmationDialog extends HTMLElement {
66
72
  </style>
67
73
  <div class="overlay" id="overlay"></div>
68
74
  <div class="confirmation-dialog" id="confirmationDialog">
69
- <h3>Confirm Action</h3>
70
- <p id="confirmationMessage"></p>
75
+ <h2 class="title" id="confirmationMessage"></h2>
71
76
  <div class="buttons">
72
77
  <button class="confirm" id="confirmButton">Confirm</button>
73
78
  <button class="cancel" id="cancelButton">Cancel</button>
@@ -0,0 +1,160 @@
1
+ class EditJsonSheet extends HTMLElement {
2
+ constructor() {
3
+ super();
4
+ this.onSubmit = null;
5
+ this.attachShadow({mode: 'open'});
6
+ this.render();
7
+
8
+ this.sheet = this.shadowRoot.querySelector('#sheet');
9
+ this.overlay = this.shadowRoot.getElementById('overlay');
10
+ this.titleText = this.shadowRoot.getElementById('title');
11
+ this.valueInput = this.shadowRoot.querySelector('#valueInput');
12
+
13
+ this.shadowRoot.querySelector('#editJsonSheet').onsubmit = (e) => this.handleSubmit(e);
14
+ this.overlay.onclick = () => this.hideSheet();
15
+ }
16
+
17
+ render() {
18
+ this.shadowRoot.innerHTML = `
19
+ <style>
20
+ .bottom-sheet {
21
+ display: flex;
22
+ flex-direction: column; /* Stack children vertically */
23
+ position: fixed;
24
+ bottom: -100%;
25
+ left: 0;
26
+ right: 0;
27
+ background-color: var(--background-color);
28
+ padding: 21px;
29
+ box-shadow: 0 -3.5px 14px rgba(0, 0, 0, 0.2);
30
+ transition: bottom 0.3s ease-out;
31
+ z-index: 1000;
32
+ border-top-left-radius: 17.5px;
33
+ border-top-right-radius: 17.5px;
34
+ height: 70vh; /* Height set to 70% of viewport height */
35
+ overflow-y: auto; /* Enable scrolling if content overflows */
36
+ max-width: 60%;
37
+ margin: 0 auto;
38
+ align-items: stretch; /* Allow children to stretch */
39
+ }
40
+ .bottom-sheet.show {
41
+ bottom: 0;
42
+ }
43
+ .bottom-sheet h3 {
44
+ color: var(--primary-color);
45
+ margin-top: 0;
46
+ margin-bottom: 14px;
47
+ font-size: 16.8px;
48
+ }
49
+ .overlay {
50
+ display: none;
51
+ position: fixed;
52
+ top: 0;
53
+ left: 0;
54
+ right: 0;
55
+ bottom: 0;
56
+ background: rgba(0, 0, 0, 0.5);
57
+ z-index: 999;
58
+ }
59
+ .show {
60
+ display: block;
61
+ }
62
+ .sheet-title {
63
+ color: var(--text-color);
64
+ }
65
+ .form-group {
66
+ max-width: 98%;
67
+ margin-bottom: 14px;
68
+ flex-grow: 1; /* Allow form group to grow */
69
+ }
70
+ .form-group label {
71
+ display: block;
72
+ margin-bottom: 5.6px;
73
+ font-weight: bold;
74
+ font-size: 11.2px;
75
+ }
76
+ .form-group input, .form-group textarea {
77
+ padding: 8.4px;
78
+ border: 1px solid var(--border-color);
79
+ border-radius: 2.8px;
80
+ font-size: 11.2px;
81
+ width: 100%;
82
+ }
83
+ .form-group textarea {
84
+ height: 100%; /* Take 50% of the bottom-sheet height */
85
+ min-height: 300px; /* Ensure a minimum height */
86
+ resize: vertical; /* Allow vertical resizing */
87
+ font-family: monospace;
88
+ flex-grow: 1; /* Allow textarea to grow */
89
+ background-color: var(--background-color);
90
+ color: var(--text-color);
91
+ border: 1px solid var(--border-color);
92
+ }
93
+ .submit-button {
94
+ min-width: 30%;
95
+ display: block;
96
+ margin: 0 auto;
97
+ padding: 10.5px;
98
+ font-size: 12.6px;
99
+ background-color: var(--primary-color);
100
+ color: white;
101
+ border: none;
102
+ border-radius: 2.8px;
103
+ cursor: pointer;
104
+ transition: background-color 0.3s ease;
105
+ }
106
+ .submit-button:hover {
107
+ background-color: var(--hover);
108
+ }
109
+ </style>
110
+
111
+ <div id="overlay" class="overlay"></div>
112
+ <div class="bottom-sheet" id="sheet">
113
+ <h2 class="sheet-title" id="title"></h2>
114
+ <form id="editJsonSheet">
115
+ <div class="form-group">
116
+ <textarea id="valueInput" name="valueInput" placeholder='Enter a value' required></textarea>
117
+ </div>
118
+ <button type="submit" class="submit-button">Submit</button>
119
+ </form>
120
+ </div>
121
+ `;
122
+ }
123
+
124
+ show(value, title, onSubmit) {
125
+ this.titleText.textContent = title
126
+ this.onSubmit = onSubmit;
127
+ this.valueInput.value = value;
128
+
129
+ this.sheet.style.display = 'block';
130
+ this.overlay.classList.add('show');
131
+ setTimeout(() => this.sheet.classList.add('show'), 10);
132
+ }
133
+
134
+ hideSheet() {
135
+ this.sheet.classList.remove('show');
136
+ this.overlay.classList.remove('show');
137
+ setTimeout(() => {
138
+ this.sheet.style.display = 'none';
139
+ }, 300);
140
+ }
141
+
142
+ handleSubmit(e) {
143
+ e.preventDefault();
144
+ let valueInput = this.valueInput.value;
145
+
146
+ try {
147
+ let data = JSON.parse(valueInput)
148
+ this.onSubmit(data);
149
+ } catch (e) {
150
+ console.error("Invalid JSON:", e);
151
+ alert(e)
152
+ return;
153
+ }
154
+
155
+ this.hideSheet();
156
+ }
157
+
158
+ }
159
+
160
+ customElements.define('edit-json-sheet', EditJsonSheet);
@@ -10,7 +10,7 @@ class MessageBottomSheet extends HTMLElement {
10
10
  bottom: 0;
11
11
  left: 0;
12
12
  right: 0;
13
- background-color: white;
13
+ background-color: var(--background-color);
14
14
  border-top-left-radius: 14px;
15
15
  border-top-right-radius: 14px;
16
16
  box-shadow: 0 -1.4px 7px rgba(0, 0, 0, 0.1);
@@ -18,7 +18,7 @@ class MessageBottomSheet extends HTMLElement {
18
18
  padding: 14px;
19
19
  transition: transform 0.3s ease-out;
20
20
  transform: translateY(100%);
21
- max-width: 700px;
21
+ max-width: 60%;
22
22
  margin: 0 auto;
23
23
  width: 100%;
24
24
  }
@@ -26,7 +26,7 @@ class MessageBottomSheet extends HTMLElement {
26
26
  transform: translateY(0);
27
27
  }
28
28
  .message-content {
29
- max-height: 210px; /* Reduced from 300px */
29
+ max-height: 50%;
30
30
  overflow-y: auto;
31
31
  margin-bottom: 14px;
32
32
  }
@@ -42,7 +42,7 @@ class MessageBottomSheet extends HTMLElement {
42
42
  font-size: 11.2px;
43
43
  }
44
44
  .close-message:hover {
45
- background-color: #0056b3;
45
+ background-color: var(--hover);
46
46
  }
47
47
  </style>
48
48
  <div class="message-bottom-sheet" id="messageBottomSheet">
@@ -55,7 +55,7 @@ class MessageBottomSheet extends HTMLElement {
55
55
  this.messageBottomSheet = this.shadowRoot.getElementById('messageBottomSheet');
56
56
  this.messageContent = this.shadowRoot.getElementById('messageContent');
57
57
  this.closeMessageButton = this.shadowRoot.getElementById('closeMessage');
58
- this.overlay = this.shadowRoot.getElementById('overlay');
58
+ this.overlay = this.shadowRoot.getElementById('overlay');
59
59
 
60
60
  this.closeMessageButton.onclick = () => this.hideMessage();
61
61
  this.overlay.onclick = () => this.hideMessage();
@@ -30,7 +30,7 @@ class OnboardBrandBottomSheet extends HTMLElement {
30
30
  bottom: 0;
31
31
  left: 0;
32
32
  right: 0;
33
- background-color: white;
33
+ background-color: var(--background-color);
34
34
  border-top-left-radius: 14px;
35
35
  border-top-right-radius: 14px;
36
36
  box-shadow: 0 -1.4px 7px rgba(0, 0, 0, 0.1);
@@ -71,6 +71,11 @@ class OnboardBrandBottomSheet extends HTMLElement {
71
71
  border: 0.7px solid var(--border-color, #E1E4E8);
72
72
  border-radius: 3.5px;
73
73
  font-size: 11.2px;
74
+ background-color: var(--background-color);
75
+ <<<<<<< HEAD
76
+ =======
77
+ color: var(--text-color);
78
+ >>>>>>> develop
74
79
  }
75
80
  .tooltip {
76
81
  position: relative;
@@ -107,9 +112,10 @@ class OnboardBrandBottomSheet extends HTMLElement {
107
112
  cursor: pointer;
108
113
  font-size: 11.2px;
109
114
  transition: background-color 0.3s ease;
115
+ margin-top: 30px;
110
116
  }
111
117
  .onboard-brand-button:hover {
112
- background-color: #3a7bc8;
118
+ background-color: var(--hover);
113
119
  }
114
120
  </style>
115
121
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.6.0/css/all.min.css">
@@ -117,7 +123,7 @@ class OnboardBrandBottomSheet extends HTMLElement {
117
123
  <div>
118
124
  <div class="overlay" id="overlay"></div>
119
125
  <div class="bottom-sheet" id="onboardBrandSheet">
120
- <h3 id="sheetTitle">Onboard New Brand</h3>
126
+ <h2 id="sheetTitle">Onboard New Brand</h2>
121
127
  <form class="onboard-brand-form" id="onboardBrandForm">
122
128
  <div class="form-group">
123
129
  <label for="brandKey">
@@ -15,6 +15,7 @@ class BaseHandler
15
15
  res.status = status
16
16
  res.body = JSON.generate({ success: false, error: "#{message}: #{error.message}" })
17
17
  res.content_type = 'application/json'
18
+ Solara.logger.error(error)
18
19
  end
19
20
 
20
21
  def method_not_allowed(res)
@@ -33,11 +33,7 @@ class EditSectionHandler < BaseHandler
33
33
  path = template[:path]
34
34
 
35
35
  if File.exist?(path)
36
- if key === 'InfoPlist.xcstrings'
37
- InfoPListStringCatalogManager.new(FilePath.brand_infoplist_string_catalog(brand_key)).update(data)
38
- else
39
- File.write(path, JSON.pretty_generate(data))
40
- end
36
+ File.write(path, JSON.pretty_generate(data))
41
37
  Solara.logger.debug("Updated Config for #{path}: #{data}")
42
38
  else
43
39
  raise "Config file not found: #{path}"
@@ -26,18 +26,6 @@ class OnboardBrandHandler < BaseHandler
26
26
  end
27
27
  res.content_type = 'application/json'
28
28
  end
29
-
30
- def onboard_brand(brand_name, brand_key, clone_brand_key = nil)
31
- if BrandsManager.instance.exists(brand_key)
32
- return { success: false, message: "Brand with key (#{brand_key}) already added!" }
33
- end
34
- SolaraManager.new.onboard(brand_key, brand_name, clone_brand_key: clone_brand_key, open_dashboard: false)
35
- { success: true, message: "Brand added successfully" }
36
- rescue StandardError => e
37
- Solara.logger.failure("Error adding brand: #{e.message}")
38
- raise
39
- end
40
-
41
29
  end
42
30
 
43
31
  def onboard_brand(brand_name, brand_key, clone_brand_key = nil)
@@ -46,8 +34,5 @@ class OnboardBrandHandler < BaseHandler
46
34
  end
47
35
  SolaraManager.new.onboard(brand_key, brand_name, clone_brand_key: clone_brand_key, open_dashboard: false)
48
36
  { success: true, message: "Brand added successfully" }
49
- rescue StandardError => e
50
- Solara.logger.failure("Error adding brand: #{e.message}")
51
- raise
52
37
  end
53
38
  end
@@ -31,13 +31,6 @@
31
31
  "name": {
32
32
  "type": "string"
33
33
  },
34
- "inputType": {
35
- "type": "string",
36
- "enum": [
37
- "color",
38
- "text"
39
- ]
40
- },
41
34
  "content": {
42
35
  "type": "object",
43
36
  "additionalProperties": {}
@@ -46,7 +39,6 @@
46
39
  "required": [
47
40
  "key",
48
41
  "name",
49
- "inputType",
50
42
  "content"
51
43
  ]
52
44
  }
@@ -0,0 +1,30 @@
1
+ {
2
+ "type": "object",
3
+ "properties": {
4
+ "files": {
5
+ "type": "array",
6
+ "items": {
7
+ "type": "object",
8
+ "properties": {
9
+ "source": {
10
+ "type": "string"
11
+ },
12
+ "destination": {
13
+ "type": "string"
14
+ },
15
+ "mandatory": {
16
+ "type": "boolean"
17
+ }
18
+ },
19
+ "required": [
20
+ "source",
21
+ "destination",
22
+ "mandatory"
23
+ ]
24
+ }
25
+ }
26
+ },
27
+ "required": [
28
+ "files"
29
+ ]
30
+ }
@@ -0,0 +1,39 @@
1
+ {
2
+ "type": "object",
3
+ "properties": {
4
+ "files": {
5
+ "type": "array",
6
+ "items": {
7
+ "type": "object",
8
+ "properties": {
9
+ "fileName": {
10
+ "type": "string"
11
+ },
12
+ "generate": {
13
+ "type": "boolean"
14
+ },
15
+ "parentClassName": {
16
+ "type": "string"
17
+ },
18
+ "customClassNames": {
19
+ "type": "array",
20
+ "items": {
21
+ "type": "object",
22
+ "properties": {
23
+ "originalName": {
24
+ "type": "string"
25
+ },
26
+ "customName": {
27
+ "type": "string"
28
+ }
29
+ },
30
+ "required": ["originalName", "customName"]
31
+ }
32
+ }
33
+ },
34
+ "required": ["fileName", "generate", "parentClassName", "customClassNames"]
35
+ }
36
+ }
37
+ },
38
+ "required": ["files"]
39
+ }
@@ -25,6 +25,15 @@ structure:
25
25
  - type: valid_json
26
26
  - type: json_schema
27
27
  schema_path: platform/android/android_signing.json
28
+ json:
29
+ type: directory
30
+ contents:
31
+ json_manifest.json:
32
+ type: file
33
+ validations:
34
+ - type: valid_json
35
+ - type: json_schema
36
+ schema_path: platform/json_manifest.json
28
37
  ios:
29
38
  type: directory
30
39
  contents:
@@ -51,6 +60,15 @@ structure:
51
60
  contents:
52
61
  AppIcon.appiconset:
53
62
  type: directory
63
+ json:
64
+ type: directory
65
+ contents:
66
+ json_manifest.json:
67
+ type: file
68
+ validations:
69
+ - type: valid_json
70
+ - type: json_schema
71
+ schema_path: platform/json_manifest.json
54
72
  shared:
55
73
  type: directory
56
74
  contents:
@@ -64,6 +82,22 @@ structure:
64
82
  type: file
65
83
  validations:
66
84
  - type: valid_json
85
+ ../../global:
86
+ type: directory
87
+ contents:
88
+ resources_manifest.json:
89
+ type: file
90
+ validations:
91
+ - type: valid_json
67
92
  - type: json_schema
68
- schema_path: platform/shared/theme.json
93
+ schema_path: platform/global/resources_manifest.json
94
+ json:
95
+ type: directory
96
+ contents:
97
+ json_manifest.json:
98
+ type: file
99
+ validations:
100
+ - type: valid_json
101
+ - type: json_schema
102
+ schema_path: platform/json_manifest.json
69
103
  strict: false
@@ -1,4 +1,16 @@
1
1
  structure:
2
+ flutter:
3
+ type: directory
4
+ contents:
5
+ json:
6
+ type: directory
7
+ contents:
8
+ json_manifest.json:
9
+ type: file
10
+ validations:
11
+ - type: valid_json
12
+ - type: json_schema
13
+ schema_path: platform/json_manifest.json
2
14
  android:
3
15
  type: directory
4
16
  contents:
@@ -64,6 +76,23 @@ structure:
64
76
  type: file
65
77
  validations:
66
78
  - type: valid_json
79
+
80
+ ../../global:
81
+ type: directory
82
+ contents:
83
+ resources_manifest.json:
84
+ type: file
85
+ validations:
86
+ - type: valid_json
67
87
  - type: json_schema
68
- schema_path: platform/shared/theme.json
88
+ schema_path: platform/global/resources_manifest.json
89
+ json:
90
+ type: directory
91
+ contents:
92
+ json_manifest.json:
93
+ type: file
94
+ validations:
95
+ - type: valid_json
96
+ - type: json_schema
97
+ schema_path: platform/json_manifest.json
69
98
  strict: false
@@ -25,6 +25,15 @@ structure:
25
25
  - type: valid_json
26
26
  - type: json_schema
27
27
  schema_path: platform/android/android_signing.json
28
+ json:
29
+ type: directory
30
+ contents:
31
+ json_manifest.json:
32
+ type: file
33
+ validations:
34
+ - type: valid_json
35
+ - type: json_schema
36
+ schema_path: platform/json_manifest.json
28
37
  ios:
29
38
  type: directory
30
39
  contents:
@@ -51,6 +60,15 @@ structure:
51
60
  contents:
52
61
  AppIcon.appiconset:
53
62
  type: directory
63
+ json:
64
+ type: directory
65
+ contents:
66
+ json_manifest.json:
67
+ type: file
68
+ validations:
69
+ - type: valid_json
70
+ - type: json_schema
71
+ schema_path: platform/json_manifest.json
54
72
  shared:
55
73
  type: directory
56
74
  contents:
@@ -64,6 +82,22 @@ structure:
64
82
  type: file
65
83
  validations:
66
84
  - type: valid_json
85
+ ../../global:
86
+ type: directory
87
+ contents:
88
+ resources_manifest.json:
89
+ type: file
90
+ validations:
91
+ - type: valid_json
67
92
  - type: json_schema
68
- schema_path: platform/shared/theme.json
93
+ schema_path: platform/global/resources_manifest.json
94
+ json:
95
+ type: directory
96
+ contents:
97
+ json_manifest.json:
98
+ type: file
99
+ validations:
100
+ - type: valid_json
101
+ - type: json_schema
102
+ schema_path: platform/json_manifest.json
69
103
  strict: false
@@ -29,7 +29,7 @@ class TemplateValidator
29
29
  when 'file'
30
30
  validate_file(errors, path, details)
31
31
  else
32
- errors << "Unknown type '#{details['type']}' for #{path.relative_path_from(@project_path)}"
32
+ errors << "Unknown type '#{details['type']}' for #{path}"
33
33
  end
34
34
  end
35
35
  end
@@ -39,7 +39,7 @@ class TemplateValidator
39
39
 
40
40
  def validate_directory(errors, path, details)
41
41
  unless path.directory?
42
- errors << "Missing directory: #{path.relative_path_from(@project_path)}"
42
+ errors << "Missing directory: #{path}"
43
43
  return
44
44
  end
45
45
  validate_structure(errors, path, details['contents']) if details['contents']
@@ -47,7 +47,7 @@ class TemplateValidator
47
47
 
48
48
  def validate_file(errors, path, details)
49
49
  unless path.file?
50
- errors << "Missing file: #{path.relative_path_from(@project_path)}"
50
+ errors << "Missing file: #{path}"
51
51
  return
52
52
  end
53
53
 
@@ -57,12 +57,12 @@ class TemplateValidator
57
57
  case validation['type']
58
58
  when 'content_includes'
59
59
  unless content.include?(validation['value'])
60
- errors << "File #{path.relative_path_from(@project_path)} does not contain expected content: #{validation['value']}"
60
+ errors << "File #{path} does not contain expected content: #{validation['value']}"
61
61
  end
62
62
 
63
63
  when 'content_matches'
64
64
  unless content.match?(Regexp.new(validation['value']))
65
- errors << "File #{path.relative_path_from(@project_path)} does not match expected pattern: #{validation['value']}"
65
+ errors << "File #{path} does not match expected pattern: #{validation['value']}"
66
66
  end
67
67
 
68
68
  when 'file_size'
@@ -70,10 +70,10 @@ class TemplateValidator
70
70
  min_size = validation['min_size']
71
71
  max_size = validation['max_size']
72
72
  if min_size && size < min_size
73
- errors << "File #{path.relative_path_from(@project_path)} is smaller than expected: #{size} < #{min_size} bytes"
73
+ errors << "File #{path} is smaller than expected: #{size} < #{min_size} bytes"
74
74
  end
75
75
  if max_size && size > max_size
76
- errors << "File #{path.relative_path_from(@project_path)} is larger than expected: #{size} > #{max_size} bytes"
76
+ errors << "File #{path} is larger than expected: #{size} > #{max_size} bytes"
77
77
  end
78
78
 
79
79
  when 'valid_json'
@@ -92,7 +92,7 @@ class TemplateValidator
92
92
  end
93
93
 
94
94
  else
95
- errors << "Unknown validation type '#{validation['type']}' for #{path.relative_path_from(@project_path)}"
95
+ errors << "Unknown validation type '#{validation['type']}' for #{path}"
96
96
  end
97
97
  end
98
98
  end
@@ -101,7 +101,7 @@ class TemplateValidator
101
101
  expected_names = expected_structure.keys
102
102
  current_path.children.each do |child|
103
103
  unless expected_names.include?(child.basename.to_s)
104
- errors << "Unexpected #{child.directory? ? 'directory' : 'file'}: #{child.relative_path_from(@project_path)}"
104
+ errors << "Unexpected #{child.directory? ? 'directory' : 'file'}: #{child}"
105
105
  end
106
106
  end
107
107
  end