@buaa_smat/hometrans 0.1.0 → 0.1.2

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 (136) hide show
  1. package/README.md +141 -124
  2. package/agents/build-fixer.md +1 -0
  3. package/agents/code-review-fix.md +1 -0
  4. package/agents/code-reviewer.md +1 -0
  5. package/agents/logic-coding.md +1 -0
  6. package/agents/logic-context-builder.md +1 -0
  7. package/agents/review-fixer.md +1 -0
  8. package/agents/self-test-fixer.md +1 -0
  9. package/agents/self-tester.md +260 -233
  10. package/agents/spec-generator.md +1 -0
  11. package/agents/test-tools/autotest/README.md +223 -0
  12. package/agents/test-tools/autotest/config.yaml.example +58 -0
  13. package/agents/test-tools/autotest/pyproject.toml +16 -0
  14. package/agents/test-tools/autotest/report_tool.py +759 -0
  15. package/agents/test-tools/autotest/self_test_runner.py +773 -0
  16. package/agents/test-tools/autotest/testcases_schema.md +143 -0
  17. package/agents/test-tools/autotest/testcases_tool.py +215 -0
  18. package/agents/test-tools/autotest/uv.lock +3156 -0
  19. package/agents/test-tools/harmony_autotest-0.1.0-py3-none-any.whl +0 -0
  20. package/agents/test-tools/hypium-6.1.0.210-py3-none-any.whl +0 -0
  21. package/agents/test-tools/hypium_mcp-0.6.5-py3-none-any.whl +0 -0
  22. package/agents/test-tools/xdevice-6.1.0.210-py3-none-any.whl +0 -0
  23. package/agents/test-tools/xdevice_devicetest-6.1.0.210-py3-none-any.whl +0 -0
  24. package/agents/test-tools/xdevice_ohos-6.1.0.210-py3-none-any.whl +0 -0
  25. package/dist/cli/config-store.js +27 -2
  26. package/dist/cli/config.js +17 -6
  27. package/dist/cli/index.js +3 -2
  28. package/dist/cli/init.js +135 -22
  29. package/dist/cli/mcp.js +2 -2
  30. package/dist/context/index.js +165 -69
  31. package/package.json +59 -60
  32. package/skills/code-dev-review-fix/SKILL.md +279 -0
  33. package/skills/code-dev-review-fix-workspace/evals/evals.json +56 -0
  34. package/skills/code-dev-review-fix-workspace/iteration-1/routing-results.md +23 -0
  35. package/skills/convert_pipeline/SKILL.md +423 -439
  36. package/skills/hmos-resources-convert/SKILL.md +623 -0
  37. package/skills/hmos-resources-convert/evals/evals.json +171 -0
  38. package/skills/hmos-resources-convert/references/conversion-rules.md +663 -0
  39. package/skills/hmos-resources-convert/references/dependency-analysis-rules.md +388 -0
  40. package/skills/hmos-resources-convert/references/resource-mapping-rules.md +457 -0
  41. package/skills/hmos-resources-convert/references/xml-drawable-to-svg-rules.md +513 -0
  42. package/skills/hmos-resources-convert/template/AppScope/app.json5 +10 -0
  43. package/skills/hmos-resources-convert/template/AppScope/resources/base/element/string.json +8 -0
  44. package/skills/hmos-resources-convert/template/AppScope/resources/base/media/background.png +0 -0
  45. package/skills/hmos-resources-convert/template/AppScope/resources/base/media/foreground.png +0 -0
  46. package/skills/hmos-resources-convert/template/AppScope/resources/base/media/layered_image.json +7 -0
  47. package/skills/hmos-resources-convert/template/build-profile.json5 +42 -0
  48. package/skills/hmos-resources-convert/template/code-linter.json5 +32 -0
  49. package/skills/hmos-resources-convert/template/entry/build-profile.json5 +33 -0
  50. package/skills/hmos-resources-convert/template/entry/hvigorfile.ts +6 -0
  51. package/skills/hmos-resources-convert/template/entry/obfuscation-rules.txt +23 -0
  52. package/skills/hmos-resources-convert/template/entry/oh-package.json5 +10 -0
  53. package/skills/hmos-resources-convert/template/entry/src/main/ets/entryability/EntryAbility.ets +48 -0
  54. package/skills/hmos-resources-convert/template/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets +16 -0
  55. package/skills/hmos-resources-convert/template/entry/src/main/ets/pages/Index.ets +23 -0
  56. package/skills/hmos-resources-convert/template/entry/src/main/module.json5 +55 -0
  57. package/skills/hmos-resources-convert/template/entry/src/main/resources/base/element/color.json +8 -0
  58. package/skills/hmos-resources-convert/template/entry/src/main/resources/base/element/float.json +8 -0
  59. package/skills/hmos-resources-convert/template/entry/src/main/resources/base/element/string.json +16 -0
  60. package/skills/hmos-resources-convert/template/entry/src/main/resources/base/media/background.png +0 -0
  61. package/skills/hmos-resources-convert/template/entry/src/main/resources/base/media/foreground.png +0 -0
  62. package/skills/hmos-resources-convert/template/entry/src/main/resources/base/media/layered_image.json +7 -0
  63. package/skills/hmos-resources-convert/template/entry/src/main/resources/base/media/startIcon.png +0 -0
  64. package/skills/hmos-resources-convert/template/entry/src/main/resources/base/profile/backup_config.json +3 -0
  65. package/skills/hmos-resources-convert/template/entry/src/main/resources/base/profile/main_pages.json +5 -0
  66. package/skills/hmos-resources-convert/template/entry/src/main/resources/dark/element/color.json +8 -0
  67. package/skills/hmos-resources-convert/template/entry/src/mock/mock-config.json5 +2 -0
  68. package/skills/hmos-resources-convert/template/entry/src/ohosTest/ets/test/Ability.test.ets +35 -0
  69. package/skills/hmos-resources-convert/template/entry/src/ohosTest/ets/test/List.test.ets +5 -0
  70. package/skills/hmos-resources-convert/template/entry/src/ohosTest/module.json5 +16 -0
  71. package/skills/hmos-resources-convert/template/entry/src/test/List.test.ets +5 -0
  72. package/skills/hmos-resources-convert/template/entry/src/test/LocalUnit.test.ets +33 -0
  73. package/skills/hmos-resources-convert/template/hvigor/hvigor-config.json5 +23 -0
  74. package/skills/hmos-resources-convert/template/hvigorfile.ts +6 -0
  75. package/skills/hmos-resources-convert/template/oh-package-lock.json5 +28 -0
  76. package/skills/hmos-resources-convert/template/oh-package.json5 +10 -0
  77. package/skills/hmos-resources-convert/tools/apktool.bat +85 -0
  78. package/skills/hmos-resources-convert/tools/apktool_3.0.1.jar +0 -0
  79. package/skills/hmos-ui-align/SKILL.md +182 -0
  80. package/skills/hmos-ui-align/config-example.json +11 -0
  81. package/skills/hmos-ui-align/config.json +11 -0
  82. package/skills/hmos-ui-align/diff_analysis.md +53 -0
  83. package/skills/hmos-ui-align/page_align.md +62 -0
  84. package/skills/hmos-ui-align/readme.md +231 -0
  85. package/skills/hmos-ui-align/references/Comparison_Template.md +2 -0
  86. package/skills/hmos-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/@Link/350/243/205/351/245/260/345/231/250/357/274/232/347/210/266/345/255/220/345/217/214/345/220/221/345/220/214/346/255/245.md +648 -0
  87. package/skills/hmos-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/@Observed/350/243/205/351/245/260/345/231/250/345/222/214@ObjectLink/350/243/205/351/245/260/345/231/250/357/274/232/345/265/214/345/245/227/347/261/273/345/257/271/350/261/241/345/261/236/346/200/247/345/217/230/345/214/226.md +2089 -0
  88. package/skills/hmos-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/@Prop/350/243/205/351/245/260/345/231/250/357/274/232/347/210/266/345/255/220/345/215/225/345/220/221/345/220/214/346/255/245.md +1033 -0
  89. package/skills/hmos-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/@Provide/350/243/205/351/245/260/345/231/250/345/222/214@Consume/350/243/205/351/245/260/345/231/250/357/274/232/344/270/216/345/220/216/344/273/243/347/273/204/344/273/266/345/217/214/345/220/221/345/220/214/346/255/245.md +1183 -0
  90. package/skills/hmos-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/@State/350/243/205/351/245/260/345/231/250/357/274/232/347/273/204/344/273/266/345/206/205/347/212/266/346/200/201.md +576 -0
  91. package/skills/hmos-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/@Track/350/243/205/351/245/260/345/231/250/357/274/232class/345/257/271/350/261/241/345/261/236/346/200/247/347/272/247/346/233/264/346/226/260.md +297 -0
  92. package/skills/hmos-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/@Watch/350/243/205/351/245/260/345/231/250/357/274/232/347/212/266/346/200/201/345/217/230/351/207/217/346/233/264/346/224/271/351/200/232/347/237/245.md +395 -0
  93. package/skills/hmos-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/AppStorage/357/274/232/345/272/224/347/224/250/345/205/250/345/261/200/347/232/204UI/347/212/266/346/200/201/345/255/230/345/202/250.md +903 -0
  94. package/skills/hmos-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/Environment/357/274/232/350/256/276/345/244/207/347/216/257/345/242/203/346/237/245/350/257/242.md +106 -0
  95. package/skills/hmos-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/LocalStorage/357/274/232/351/241/265/351/235/242/347/272/247UI/347/212/266/346/200/201/345/255/230/345/202/250.md +1178 -0
  96. package/skills/hmos-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/MVVM/346/250/241/345/274/217V1.md +911 -0
  97. package/skills/hmos-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/MVVM/346/250/241/345/274/217/357/274/210V1/357/274/211.md +911 -0
  98. package/skills/hmos-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/PersistentStorage/357/274/232/346/214/201/344/271/205/345/214/226/345/255/230/345/202/250UI/347/212/266/346/200/201.md +355 -0
  99. package/skills/hmos-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243//347/256/241/347/220/206/345/272/224/347/224/250/346/213/245/346/234/211/347/232/204/347/212/266/346/200/201/346/246/202/350/277/260.md +11 -0
  100. package/skills/hmos-ui-align/references/UI_Analysis_Template.md +4 -0
  101. package/skills/hmos-ui-align/references/android-to-harmonyOS-ui-atomic-component-mapping-reference.md +2535 -0
  102. package/skills/hmos-ui-align/references/android-to-harmonyOS-ui-interaction-mapping-reference.md +555 -0
  103. package/skills/hmos-ui-align/references/android-to-harmonyOS-ui-layout-mapping-reference.md +117 -0
  104. package/skills/hmos-ui-align/scripts/app_feature_verify.py +443 -0
  105. package/skills/hmos-ui-align/scripts/navigation-capure.md +37 -0
  106. package/skills/hmos-ui-align/scripts/page_capture.py +592 -0
  107. package/skills/hmos-ui-align-batch/SKILL.md +99 -0
  108. package/skills/hmos-ui-align-batch/references/conversion-procedure.md +180 -0
  109. package/skills/hmos-ui-align-batch/references/mappings/android-to-harmonyOS-ui-atomic-component-mapping-reference.md +2535 -0
  110. package/skills/hmos-ui-align-batch/references/mappings/android-to-harmonyOS-ui-interaction-mapping-reference.md +555 -0
  111. package/skills/hmos-ui-align-batch/references/mappings/android-to-harmonyOS-ui-layout-mapping-reference.md +117 -0
  112. package/skills/hmos-ui-align-batch/references/mvvm/@Link/350/243/205/351/245/260/345/231/250/357/274/232/347/210/266/345/255/220/345/217/214/345/220/221/345/220/214/346/255/245.md +648 -0
  113. package/skills/hmos-ui-align-batch/references/mvvm/@Observed/350/243/205/351/245/260/345/231/250/345/222/214@ObjectLink/350/243/205/351/245/260/345/231/250/357/274/232/345/265/214/345/245/227/347/261/273/345/257/271/350/261/241/345/261/236/346/200/247/345/217/230/345/214/226.md +2089 -0
  114. package/skills/hmos-ui-align-batch/references/mvvm/@Prop/350/243/205/351/245/260/345/231/250/357/274/232/347/210/266/345/255/220/345/215/225/345/220/221/345/220/214/346/255/245.md +1033 -0
  115. package/skills/hmos-ui-align-batch/references/mvvm/@Provide/350/243/205/351/245/260/345/231/250/345/222/214@Consume/350/243/205/351/245/260/345/231/250/357/274/232/344/270/216/345/220/216/344/273/243/347/273/204/344/273/266/345/217/214/345/220/221/345/220/214/346/255/245.md +1183 -0
  116. package/skills/hmos-ui-align-batch/references/mvvm/@State/350/243/205/351/245/260/345/231/250/357/274/232/347/273/204/344/273/266/345/206/205/347/212/266/346/200/201.md +576 -0
  117. package/skills/hmos-ui-align-batch/references/mvvm/@Track/350/243/205/351/245/260/345/231/250/357/274/232class/345/257/271/350/261/241/345/261/236/346/200/247/347/272/247/346/233/264/346/226/260.md +297 -0
  118. package/skills/hmos-ui-align-batch/references/mvvm/@Watch/350/243/205/351/245/260/345/231/250/357/274/232/347/212/266/346/200/201/345/217/230/351/207/217/346/233/264/346/224/271/351/200/232/347/237/245.md +395 -0
  119. package/skills/hmos-ui-align-batch/references/mvvm/AppStorage/357/274/232/345/272/224/347/224/250/345/205/250/345/261/200/347/232/204UI/347/212/266/346/200/201/345/255/230/345/202/250.md +903 -0
  120. package/skills/hmos-ui-align-batch/references/mvvm/Environment/357/274/232/350/256/276/345/244/207/347/216/257/345/242/203/346/237/245/350/257/242.md +106 -0
  121. package/skills/hmos-ui-align-batch/references/mvvm/LocalStorage/357/274/232/351/241/265/351/235/242/347/272/247UI/347/212/266/346/200/201/345/255/230/345/202/250.md +1178 -0
  122. package/skills/hmos-ui-align-batch/references/mvvm/MVVM/346/250/241/345/274/217/357/274/210V1/357/274/211.md +911 -0
  123. package/skills/hmos-ui-align-batch/references/mvvm/PersistentStorage/357/274/232/346/214/201/344/271/205/345/214/226/345/255/230/345/202/250UI/347/212/266/346/200/201.md +355 -0
  124. package/skills/hmos-ui-align-batch/references/mvvm//347/256/241/347/220/206/345/272/224/347/224/250/346/213/245/346/234/211/347/232/204/347/212/266/346/200/201/346/246/202/350/277/260.md +11 -0
  125. package/skills/hmos-ui-align-batch/scripts/android_parse_fast.py +1606 -0
  126. package/skills/self-test/SKILL.md +369 -0
  127. package/skills/self-test/readme.md +309 -0
  128. package/skills/spec-generator-skill/SKILL.md +332 -0
  129. package/skills/spec-generator-skill/references/android-platform-tokens.md +105 -0
  130. package/skills/spec-generator-skill/references/spec-sample-1.md +78 -0
  131. package/skills/spec-generator-skill/references/spec-sample-2.md +58 -0
  132. package/skills/spec-generator-skill/references/spec-sample-3.md +116 -0
  133. package/skills/spec-generator-skill/references/step4-report-template.md +33 -0
  134. package/agents/self-test-setup.md +0 -165
  135. package/dist/context/resources/sdkConfig.json +0 -24
  136. package/src/context/resources/sdkConfig.json +0 -24
@@ -0,0 +1,663 @@
1
+ # Android to HarmonyOS Resource Conversion Rules
2
+
3
+ This document contains the complete, detailed rules for converting Android resources to HarmonyOS format. Read this before performing any conversions. When producing the dedicated mapping markdown at `resource_mapping_path`, also read `references/resource-mapping-rules.md` — every conversion outcome described here must be reflected there as inventory rows and mapping rows.
4
+
5
+ ## Table of Contents
6
+ 1. [Android Resource Directory Structure](#android-resource-directory-structure)
7
+ 2. [HarmonyOS Resource Directory Structure](#harmonyos-resource-directory-structure)
8
+ 3. [Values XML to Element JSON Conversion](#values-xml-to-element-json-conversion)
9
+ 4. [Media Resource Conversion](#media-resource-conversion)
10
+ 5. [Qualifier Mapping](#qualifier-mapping)
11
+ 6. [Special Cases and Edge Cases](#special-cases-and-edge-cases)
12
+
13
+ ---
14
+
15
+ ## Android Resource Directory Structure
16
+
17
+ Android resources live under `app/src/main/res/`. Common subdirectories:
18
+
19
+ | Directory | Contents |
20
+ |---|---|
21
+ | `drawable/` | Images (PNG, JPG, GIF, WEBP, BMP) and XML drawables (shapes, selectors, layer-lists, vector drawables) |
22
+ | `drawable-<qualifier>/` | Qualified drawable variants (e.g., `drawable-hdpi`, `drawable-night`) |
23
+ | `mipmap/` | Launcher icons (usually at multiple densities) |
24
+ | `mipmap-<qualifier>/` | Qualified launcher icon variants |
25
+ | `values/` | XML files defining strings, colors, dimensions, styles, themes, arrays, etc. |
26
+ | `values-<qualifier>/` | Qualified value variants (e.g., `values-ar`, `values-zh-rCN`, `values-night`) |
27
+ | `layout/` | XML layout definitions |
28
+ | `anim/` | Tween animation XML |
29
+ | `animator/` | Property animation XML |
30
+ | `color/` | Color state list XML |
31
+ | `menu/` | Menu definition XML |
32
+ | `raw/` | Arbitrary files copied as-is |
33
+ | `xml/` | Arbitrary XML files (preferences, configs, etc.) |
34
+ | `font/` | Font files (TTF, OTF, TTC) |
35
+ | `transition/` | Transition animation XML |
36
+ | `interpolator/` | Animation interpolator XML |
37
+
38
+ ## HarmonyOS Resource Directory Structure
39
+
40
+ HarmonyOS resources live under `entry/src/main/resources/`. Structure:
41
+
42
+ ```
43
+ resources/
44
+ ├── base/ # Default resources
45
+ │ ├── element/ # Key-value resources (JSON)
46
+ │ │ ├── string.json
47
+ │ │ ├── color.json
48
+ │ │ ├── float.json
49
+ │ │ ├── integer.json
50
+ │ │ ├── boolean.json
51
+ │ │ ├── plural.json
52
+ │ │ ├── strarray.json
53
+ │ │ └── intarray.json
54
+ │ ├── media/ # Images, audio, video
55
+ │ │ ├── icon.png
56
+ │ │ └── ...
57
+ │ └── profile/ # JSON configuration files
58
+ │ └── ...
59
+ ├── <qualifier>/ # Qualified resources (e.g., zh_CN, dark, ldpi)
60
+ │ ├── element/
61
+ │ ├── media/
62
+ │ └── profile/
63
+ ├── rawfile/ # Raw files (accessed by path)
64
+ └── resfile/ # Raw files (decompressed to sandbox)
65
+ ```
66
+
67
+ ## Mapping Output Requirements
68
+
69
+ In addition to performing the actual conversion, record enough metadata to later write the markdown at `resource_mapping_path`.
70
+
71
+ ### Required recording behavior
72
+
73
+ - Every Android resource observed during conversion must create an Android resource inventory record.
74
+ - Every conversion outcome must create at least one mapping record.
75
+ - If a resource is skipped, unmappable, resolved as a system resource, treated as a library-only resource, or identified as a runtime remote resource, it still must be recorded.
76
+ - For `values/*.xml`, record inventory and mapping rows at entry granularity using `file_path#tag/name`.
77
+
78
+ ### Recording examples
79
+
80
+ - `res/drawable/icon.png` copied directly → inventory row + mapping row with `mapping_kind = direct copy`
81
+ - `res/drawable/ic_back.xml` converted to SVG → inventory row + mapping row with `mapping_kind = svg conversion`
82
+ - `res/mipmap-anydpi-v26/ic_launcher.xml` converted to layered-image JSON and a generated background PNG → one inventory row + multiple mapping rows
83
+ - `res/layout/activity_main.xml` not converted → inventory row + mapping row with `HarmonyOS Target = N/A`
84
+
85
+ ### Many-to-one and one-to-many rules
86
+
87
+ - Many Android `values` entries may land in the same HarmonyOS JSON file. Still emit one mapping row per Android source entry.
88
+ - One Android source may generate multiple HarmonyOS targets. Emit one mapping row per target.
89
+
90
+ ---
91
+
92
+
93
+ ### strings.xml → string.json
94
+
95
+ **Android format:**
96
+ ```xml
97
+ <resources>
98
+ <string name="app_name">My App</string>
99
+ <string name="greeting">Hello, %1$s! You have %2$d messages.</string>
100
+ <string name="with_apostrophe">It\'s a test</string>
101
+ <string name="with_html"><![CDATA[<b>Bold</b> text]]></string>
102
+ </resources>
103
+ ```
104
+
105
+ **HarmonyOS format:**
106
+ ```json
107
+ {
108
+ "string": [
109
+ {
110
+ "name": "app_name",
111
+ "value": "My App"
112
+ },
113
+ {
114
+ "name": "greeting",
115
+ "value": "Hello, %1$s! You have %2$d messages."
116
+ },
117
+ {
118
+ "name": "with_apostrophe",
119
+ "value": "It's a test"
120
+ },
121
+ {
122
+ "name": "with_html",
123
+ "value": "<b>Bold</b> text"
124
+ }
125
+ ]
126
+ }
127
+ ```
128
+
129
+ **Rules:**
130
+ - Remove Android escape sequences: `\'` → `'`, `\"` → `"`
131
+ - Decode XML entities: `&amp;` → `&`, `&lt;` → `<`, `&gt;` → `>`, `&quot;` → `"`, `&apos;` → `'`
132
+ - Extract text from CDATA sections
133
+ - Preserve format placeholders (`%1$s`, `%2$d`, etc.) — HarmonyOS uses the same format
134
+ - If the string value is wrapped in quotes in Android XML (`"some text"`), remove the outer quotes
135
+ - Skip `<string>` elements with `translatable="false"` attribute? No — still include them, as they may be used at runtime. But note the translatable status.
136
+
137
+ ### colors.xml → color.json
138
+
139
+ **Android format:**
140
+ ```xml
141
+ <resources>
142
+ <color name="primary">#FF6200EE</color>
143
+ <color name="background">#FFFFFF</color>
144
+ <color name="semi_transparent">#80000000</color>
145
+ <color name="shorthand">#F00</color>
146
+ </resources>
147
+ ```
148
+
149
+ **HarmonyOS format:**
150
+ ```json
151
+ {
152
+ "color": [
153
+ {
154
+ "name": "primary",
155
+ "value": "#FF6200EE"
156
+ },
157
+ {
158
+ "name": "background",
159
+ "value": "#ffFFFFFF"
160
+ },
161
+ {
162
+ "name": "semi_transparent",
163
+ "value": "#80000000"
164
+ },
165
+ {
166
+ "name": "shorthand",
167
+ "value": "#ffFF0000"
168
+ }
169
+ ]
170
+ }
171
+ ```
172
+
173
+ **Rules:**
174
+ - `#AARRGGBB` (8 digits) → keep as-is (HarmonyOS uses same format: first 2 = opacity)
175
+ - `#RRGGBB` (6 digits) → prepend `ff` → `#ffRRGGBB`
176
+ - `#ARGB` (4 digits) → expand each: `#8F00` → `#88FF0000`
177
+ - `#RGB` (3 digits) → expand each and add `ff`: `#F00` → `#ffFF0000`
178
+ - Color values are case-insensitive in Android; preserve original case or normalize
179
+
180
+ ### dimens.xml → float.json
181
+
182
+ **Android format:**
183
+ ```xml
184
+ <resources>
185
+ <dimen name="text_size">16sp</dimen>
186
+ <dimen name="margin_large">24dp</dimen>
187
+ <dimen name="border_width">1px</dimen>
188
+ <dimen name="line_height">20dp</dimen>
189
+ </resources>
190
+ ```
191
+
192
+ **HarmonyOS format:**
193
+ ```json
194
+ {
195
+ "float": [
196
+ {
197
+ "name": "text_size",
198
+ "value": "16fp"
199
+ },
200
+ {
201
+ "name": "margin_large",
202
+ "value": "24vp"
203
+ },
204
+ {
205
+ "name": "border_width",
206
+ "value": "1px"
207
+ },
208
+ {
209
+ "name": "line_height",
210
+ "value": "20vp"
211
+ }
212
+ ]
213
+ }
214
+ ```
215
+
216
+ **Unit mapping:**
217
+ | Android Unit | HarmonyOS Unit | Notes |
218
+ |---|---|---|
219
+ | `dp` | `vp` | Density-independent pixels → virtual pixels |
220
+ | `dip` | `vp` | Same as dp |
221
+ | `sp` | `fp` | Scale-independent pixels → font pixels |
222
+ | `px` | `px` | Physical pixels (keep as-is) |
223
+ | `pt` | `vp` | Points → approximate with vp (multiply by 1.33) |
224
+ | `in` | `vp` | Inches → convert to vp (multiply by 160) |
225
+ | `mm` | `vp` | Millimeters → convert to vp (multiply by 6.3) |
226
+ | (no unit) | `vp` | Plain number → append `vp` |
227
+
228
+ ### integers.xml → integer.json
229
+
230
+ **Android format:**
231
+ ```xml
232
+ <resources>
233
+ <integer name="max_items">10</integer>
234
+ <integer name="animation_duration">300</integer>
235
+ </resources>
236
+ ```
237
+
238
+ **HarmonyOS format:**
239
+ ```json
240
+ {
241
+ "integer": [
242
+ {
243
+ "name": "max_items",
244
+ "value": 10
245
+ },
246
+ {
247
+ "name": "animation_duration",
248
+ "value": 300
249
+ }
250
+ ]
251
+ }
252
+ ```
253
+
254
+ **Rules:**
255
+ - **CRITICAL**: Integer values MUST be stored as JSON number type, NOT as JSON strings. `"value": 10` is correct; `"value": "10"` is WRONG and will cause HarmonyOS compilation errors.
256
+ - Parse the XML text content as an integer using `parseInt()` or equivalent. Remove any whitespace before parsing.
257
+ - If the value is a resource reference (`@integer/other`), resolve the reference chain first, then store the final resolved value as a JSON number.
258
+ - If the value contains a hex prefix (`0x`), parse as hexadecimal and store the decimal integer result.
259
+ - If a value cannot be parsed as an integer after resolution, log a warning and use `0` as a fallback.
260
+ - Integer-array values (`<integer-array>`) follow the same rule — each `<item>` value must be a JSON number.
261
+
262
+ ### bools.xml → boolean.json
263
+
264
+ **Android format:**
265
+ ```xml
266
+ <resources>
267
+ <bool name="is_tablet">false</bool>
268
+ <bool name="show_ads">true</bool>
269
+ </resources>
270
+ ```
271
+
272
+ **HarmonyOS format:**
273
+ ```json
274
+ {
275
+ "boolean": [
276
+ {
277
+ "name": "is_tablet",
278
+ "value": false
279
+ },
280
+ {
281
+ "name": "show_ads",
282
+ "value": true
283
+ }
284
+ ]
285
+ }
286
+ ```
287
+
288
+ ### arrays.xml → strarray.json / intarray.json
289
+
290
+ **Android string-array:**
291
+ ```xml
292
+ <resources>
293
+ <string-array name="colors">
294
+ <item>Red</item>
295
+ <item>Green</item>
296
+ <item>Blue</item>
297
+ </string-array>
298
+ </resources>
299
+ ```
300
+
301
+ **HarmonyOS strarray.json:**
302
+ ```json
303
+ {
304
+ "strarray": [
305
+ {
306
+ "name": "colors",
307
+ "value": [
308
+ {
309
+ "value": "Red"
310
+ },
311
+ {
312
+ "value": "Green"
313
+ },
314
+ {
315
+ "value": "Blue"
316
+ }
317
+ ]
318
+ }
319
+ ]
320
+ }
321
+ ```
322
+
323
+ **Android integer-array:**
324
+ ```xml
325
+ <resources>
326
+ <integer-array name="scores">
327
+ <item>100</item>
328
+ <item>200</item>
329
+ <item>300</item>
330
+ </integer-array>
331
+ </resources>
332
+ ```
333
+
334
+ **HarmonyOS intarray.json:**
335
+ ```json
336
+ {
337
+ "intarray": [
338
+ {
339
+ "name": "scores",
340
+ "value": [
341
+ {
342
+ "value": 100
343
+ },
344
+ {
345
+ "value": 200
346
+ },
347
+ {
348
+ "value": 300
349
+ }
350
+ ]
351
+ }
352
+ ]
353
+ }
354
+ ```
355
+
356
+ ### plurals.xml → plural.json
357
+
358
+ **Android format:**
359
+ ```xml
360
+ <resources>
361
+ <plurals name="items_count">
362
+ <item quantity="one">%d item</item>
363
+ <item quantity="other">%d items</item>
364
+ </plurals>
365
+ </resources>
366
+ ```
367
+
368
+ **HarmonyOS format:**
369
+ ```json
370
+ {
371
+ "plural": [
372
+ {
373
+ "name": "items_count",
374
+ "value": [
375
+ {
376
+ "quantity": "one",
377
+ "value": "%d item"
378
+ },
379
+ {
380
+ "quantity": "other",
381
+ "value": "%d items"
382
+ }
383
+ ]
384
+ }
385
+ ]
386
+ }
387
+ ```
388
+
389
+ **Supported quantities (same for both):** `zero`, `one`, `two`, `few`, `many`, `other`
390
+
391
+ ---
392
+
393
+ ## Media Resource Conversion
394
+
395
+ ### Drawable images → media
396
+
397
+ Copy image files directly from Android `drawable/` to HarmonyOS `base/media/`:
398
+ - Supported formats in HarmonyOS: PNG, JPG, GIF, SVG, WEBP, BMP
399
+ - All these are also common Android formats, so direct copy works
400
+ - **Do NOT copy XML drawables** (shapes, selectors, vector drawables, layer-lists, ripple effects) — these have no direct HarmonyOS equivalent
401
+
402
+ ### Identifying XML vs image drawables
403
+
404
+ In `drawable/` directories, files can be either images or XML:
405
+ - `.png`, `.jpg`, `.jpeg`, `.gif`, `.webp`, `.bmp`, `.svg` → image files, copy to `media/`
406
+ - `.xml` → XML drawable, **convert to SVG** (see `references/xml-drawable-to-svg-rules.md` for detailed rules). HarmonyOS supports SVG natively in `media/`. Output as `<original_name>.svg` in the target `media/` directory.
407
+ - `.9.png` → nine-patch image: **rename** `.9.png` to `_9.png` before copying to `media/`. HarmonyOS does not allow `.` characters in resource filenames except for the final extension separator (e.g., `abc_btn.9.png` is an invalid HarmonyOS resource name). Replace the `.9.png` suffix with `_9.png` (e.g., `abc_btn_default.9.png` → `abc_btn_default_9.png`). This renaming must also be applied in all density-qualified directories (`drawable-hdpi/`, `drawable-xhdpi/`, etc.). Log in the conversion report that nine-patch stretching behavior is lost and the developer may need to implement equivalent stretchable behavior in ArkUI code. Also update any references to nine-patch files throughout the converted output to use the new `_9` naming.
408
+
409
+ ### XML Drawable → SVG Conversion (Summary)
410
+
411
+ Android XML drawables should be converted to SVG format for HarmonyOS. The main convertible types are:
412
+
413
+ 1. **VectorDrawable** (`<vector>`) — Most straightforward. Android's `pathData` uses the same syntax as SVG `d` attribute. Convert `<path>`, `<group>`, `<clip-path>` elements to SVG equivalents.
414
+
415
+ 2. **ShapeDrawable** (`<shape>`) — Convert rectangles, ovals, lines, and rings to SVG `<rect>`, `<ellipse>`, `<line>`, or `<circle>` elements with appropriate fill, stroke, and gradient attributes.
416
+
417
+ 3. **LayerListDrawable** (`<layer-list>`) — Each `<item>` becomes a nested SVG element, layered in document order.
418
+
419
+ 4. **StateListDrawable** (`<selector>`) — Extract the default (no-state) `<item>` or the last `<item>` as fallback, and convert it to SVG. Log the state-dependent items in the conversion report as requiring manual handling.
420
+
421
+ 5. **Unconvertible types** — `<ripple>`, `<animated-vector>`, `<animated-selector>`, `<transition>` remain logged as unmappable because they involve runtime behavior that SVG cannot represent.
422
+
423
+ For the complete, detailed conversion rules with examples, read `references/xml-drawable-to-svg-rules.md`.
424
+
425
+ ### Mipmap → media
426
+
427
+ Launcher icons from `mipmap/` directories go to `base/media/` (or qualified `media/`):
428
+ - Typically named `ic_launcher.png`, `ic_launcher_round.png`, `ic_launcher_foreground.png`, `ic_launcher_background.png`
429
+ - PNG/WEBP launcher icons → direct copy to target `media/` directory
430
+ - **Adaptive icon XML files** (`<adaptive-icon>` root element, commonly found in `mipmap-anydpi-v26/`) → convert to HarmonyOS layered-image JSON. Parse the XML, extract the `background` and `foreground` layer references, and convert them using the rules below. Output as `<original_name>_layered_image.json` in the target `media/` directory. Only `background` and `foreground` are valid keys under the `"layered-image"` object — skip `monochrome` or any other elements.
431
+
432
+ **Reference conversion rules for layered-image values:**
433
+ - `@drawable/xxx` → `$media:xxx`
434
+ - `@mipmap/xxx` → `$media:xxx`
435
+ - `@color/xxx` → **must NOT use `$color:xxx`** — `layered-image` only accepts `$media:` references. See color-background handling below.
436
+
437
+ **Color background handling (critical):**
438
+
439
+ HarmonyOS `layered-image` does not support `$color:xxx` — only `$media:xxx` is valid for both `background` and `foreground`. When an Android `<background>` (or `<foreground>`) points to a color resource (`@color/xxx`):
440
+
441
+ 1. Resolve the actual hex color value by looking it up in the converted `color.json` or the Android `colors.xml`. If the color itself references another color, follow the chain to get the final hex value.
442
+ 2. Generate a solid-color PNG image filled entirely with that hex value. Any reasonable dimensions work (e.g., 1×1 px or 108×108 px).
443
+ 3. Save the PNG as `<color_name>_bg.png` in `base/media/` (e.g., `md_orange_700_bg.png`).
444
+ 4. Use `$media:<color_name>_bg` in the layered-image JSON.
445
+
446
+ **Adaptive icon JSON format example:**
447
+
448
+ For `ic_launcher.xml`:
449
+ ```xml
450
+ <adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
451
+ <background android:drawable="@color/md_orange_700" />
452
+ <foreground android:drawable="@mipmap/ic_launcher_foreground" />
453
+ <monochrome android:drawable="@drawable/ic_launcher_monochrome" />
454
+ </adaptive-icon>
455
+ ```
456
+
457
+ Suppose `@color/md_orange_700` resolves to `#F57C00`. Generate `base/media/md_orange_700_bg.png` (solid `#F57C00`). Converts to `ic_launcher_layered_image.json`:
458
+ ```json
459
+ {
460
+ "layered-image": {
461
+ "background": "$media:md_orange_700_bg",
462
+ "foreground": "$media:ic_launcher_foreground"
463
+ }
464
+ }
465
+ ```
466
+
467
+ Note: The `monochrome` element has no HarmonyOS `layered-image` equivalent, so omit it from the JSON output. But do not ignore it entirely — the drawable it references (e.g., `@drawable/ic_launcher_monochrome`) is a real resource that should be converted as a normal drawable and included in dependency analysis. If it's missing from the source `res/` directory (i.e., it comes from a library), record it as an unsatisfied dependency and attempt to recover it via APK decompilation in Step 5, just like any other missing resource.
468
+ - **VectorDrawable XML files** (if found in mipmap directories with `<vector>` root element) → convert to SVG, same as drawable vectors
469
+
470
+ **Common pattern**: `mipmap-anydpi-v26/` is extremely common in Android projects. The qualifier `anydpi-v26` should be parsed as `anydpi` (→ `base`) + `v26` (→ strip). The files inside are typically `<adaptive-icon>` XMLs — process them by reading the XML root element to classify the content type, not by rejecting based on the directory qualifier.
471
+
472
+ ### Raw files → rawfile
473
+
474
+ Copy all files from Android `raw/` to HarmonyOS `rawfile/`:
475
+ - Preserve original filenames
476
+ - These are accessed by path in both systems
477
+
478
+ ### Font files → rawfile/fonts
479
+
480
+ Copy font files from Android `font/` to HarmonyOS `rawfile/fonts/`:
481
+ - `.ttf`, `.otf`, `.ttc` files → direct copy
482
+ - Font XML files (font family definitions) → log as unmappable
483
+
484
+ ---
485
+
486
+ ## Qualifier Mapping
487
+
488
+ ### Density Qualifiers
489
+
490
+ The naming conventions differ between Android and HarmonyOS because HarmonyOS uses different DPI range labels:
491
+
492
+ | Android Qualifier | Approx DPI | HarmonyOS Qualifier | HarmonyOS DPI Range |
493
+ |---|---|---|---|
494
+ | `ldpi` | 120 | `sdpi` | (0, 120] |
495
+ | `mdpi` | 160 | `mdpi` | (120, 160] |
496
+ | `tvdpi` | 213 | `ldpi` | (160, 240] |
497
+ | `hdpi` | 240 | `ldpi` | (160, 240] |
498
+ | `xhdpi` | 320 | `xldpi` | (240, 320] |
499
+ | `xxhdpi` | 480 | `xxldpi` | (320, 480] |
500
+ | `xxxhdpi` | 640 | `xxxldpi` | (480, 640] |
501
+ | `nodpi` | N/A | `base` | No density qualifier; use base |
502
+ | `anydpi` | N/A | `base` | No density qualifier; use base |
503
+
504
+ ### Language/Region Qualifiers
505
+
506
+ Android format: `<type>-<language>` or `<type>-<language>-r<REGION>`
507
+ HarmonyOS format: `<language>` or `<language>_<REGION>`
508
+
509
+ **Examples:**
510
+ | Android | HarmonyOS |
511
+ |---|---|
512
+ | `values-ar` | `ar/element/` |
513
+ | `values-zh` | `zh/element/` |
514
+ | `values-zh-rCN` | `zh_CN/element/` |
515
+ | `values-zh-rTW` | `zh_TW/element/` |
516
+ | `values-en` | `en/element/` |
517
+ | `values-en-rUS` | `en_US/element/` |
518
+ | `values-en-rGB` | `en_GB/element/` |
519
+ | `values-fr-rFR` | `fr_FR/element/` |
520
+ | `values-ja` | `ja/element/` |
521
+ | `values-ko` | `ko/element/` |
522
+ | `drawable-zh-rCN-hdpi` | `zh_CN-ldpi/media/` |
523
+
524
+ **Parsing Android language qualifiers:**
525
+ - Language code: 2 or 3 lowercase letters (ISO 639)
526
+ - Region code: preceded by `r`, 2 uppercase letters (ISO 3166-1) — strip the `r` prefix
527
+ - Script code (BCP 47): preceded by `b+`, e.g., `b+sr+Latn` → `sr_Latn`
528
+
529
+ ### Orientation Qualifiers
530
+
531
+ | Android | HarmonyOS |
532
+ |---|---|
533
+ | `land` | `horizontal` |
534
+ | `port` | `vertical` |
535
+
536
+ ### Night Mode Qualifiers
537
+
538
+ | Android | HarmonyOS |
539
+ |---|---|
540
+ | `night` | `dark` |
541
+ | `notnight` | `light` |
542
+
543
+ ### Combining Multiple Qualifiers
544
+
545
+ Android directory names can contain multiple qualifiers separated by hyphens, e.g., `drawable-zh-rCN-night-hdpi` or `mipmap-anydpi-v26`.
546
+
547
+ **Parsing algorithm for any Android resource directory name:**
548
+
549
+ 1. Split the directory name by `-` to get segments
550
+ 2. The first segment is the resource type (`drawable`, `mipmap`, `values`, etc.)
551
+ 3. The remaining segments are qualifiers. Parse them left-to-right, recognizing:
552
+ - Language codes: 2-3 lowercase letters (e.g., `zh`, `ar`, `en`)
553
+ - Region codes: `r` + 2 uppercase letters (e.g., `rCN`, `rUS`) — always follows a language
554
+ - Density: `ldpi`, `mdpi`, `hdpi`, `xhdpi`, `xxhdpi`, `xxxhdpi`, `nodpi`, `anydpi`, `tvdpi`
555
+ - Orientation: `land`, `port`
556
+ - Night mode: `night`, `notnight`
557
+ - API level: `v` followed by digits (e.g., `v26`, `v21`) — **strip, do not reject**
558
+ - Screen size qualifiers: `sw<N>dp`, `w<N>dp`, `h<N>dp`, `small`, `normal`, `large`, `xlarge` — **skip entire directory, mark as unmapped**
559
+ - Other unsupported qualifiers — **strip, do not reject**
560
+ 4. Map each recognized qualifier to its HarmonyOS equivalent
561
+ 5. Strip only API-level, layout direction, screen shape, HDR, and aspect qualifiers (see "Unsupported Android Qualifiers" below)
562
+ 6. If any screen-size qualifiers remain (`sw<N>dp`, `w<N>dp`, `h<N>dp`, `small`/`normal`/`large`/`xlarge`), skip the entire directory — mark all resources as "unmapped" with reason "Unsupported qualifier"
563
+ 7. If no mappable or preserved qualifiers remain after stripping, use `base/`
564
+ 8. Reassemble remaining HarmonyOS qualifiers in correct order: MCC_MNC-language_script_country/region-orientation-device-colormode-density (preserved qualifiers go at the end)
565
+
566
+ **Examples:**
567
+ | Android Directory | Type | Qualifiers | HarmonyOS Dir |
568
+ |---|---|---|---|
569
+ | `drawable-hdpi` | drawable | hdpi→ldpi | `ldpi/media/` |
570
+ | `mipmap-anydpi-v26` | mipmap | anydpi→base, v26→stripped | `base/media/` |
571
+ | `drawable-zh-rCN-night-hdpi` | drawable | zh-rCN→zh_CN, night→dark, hdpi→ldpi | `zh_CN-dark-ldpi/media/` |
572
+ | `values-ko-rKR` | values | ko-rKR→ko_KR | `ko_KR/element/` |
573
+ | `drawable-night-v21` | drawable | night→dark, v21→stripped | `dark/media/` |
574
+
575
+ ### Unsupported Android Qualifiers
576
+
577
+ These Android qualifiers have no HarmonyOS equivalent. When encountered, **strip them** from the qualifier list (do not reject the directory). If stripping leaves no remaining qualifiers, use `base/`. If other valid qualifiers remain, use those.
578
+
579
+ Unsupported qualifiers to strip:
580
+ - API level `v<N>` (e.g., `v26`, `v21`, `v31`)
581
+ - Layout direction (`ldrtl`, `ldltr`)
582
+ - `round`, `notround` (screen shape)
583
+ - `highdr`, `lowdr` (HDR)
584
+ - `long`, `notlong` (screen aspect)
585
+
586
+ **Qualifiers without a HarmonyOS equivalent** (skip entirely, do NOT convert):
587
+ - `sw<N>dp` (smallest width, e.g., `sw600dp`)
588
+ - `w<N>dp` (available width, e.g., `w480dp`, `w600dp`)
589
+ - `h<N>dp` (available height)
590
+ - `small`, `normal`, `large`, `xlarge` (screen size)
591
+
592
+ These qualifiers have no HarmonyOS mapping. When a directory's only remaining qualifiers (after stripping API level etc.) are from this list, **skip all resources in that directory entirely**. Mark them as "unmapped" in the conversion report with reason "Unsupported qualifier: no HarmonyOS equivalent". Do NOT place them in `base/` or preserve the qualifier as-is — skipping avoids incorrect conversions.
593
+
594
+ **Important: multi-qualifier directory handling.** Android directory names often combine multiple qualifiers with hyphens. When parsing, extract ALL qualifiers, map each one independently, strip any unsupported ones, and then assemble the HarmonyOS qualifier from whatever remains.
595
+
596
+ **Examples of stripping unsupported qualifiers:**
597
+
598
+ | Android Directory | Qualifiers Parsed | After Mapping | HarmonyOS Target |
599
+ |---|---|---|---|
600
+ | `mipmap-anydpi-v26` | `anydpi` + `v26` | `anydpi` → `base`, `v26` → stripped | `base/media/` |
601
+ | `drawable-night-v21` | `night` + `v21` | `night` → `dark`, `v21` → stripped | `dark/media/` |
602
+ | `values-sw600dp` | `sw600dp` | **skip — unmapped** | N/A (skipped) |
603
+ | `values-w480dp` | `w480dp` | **skip — unmapped** | N/A (skipped) |
604
+ | `drawable-hdpi-v4` | `hdpi` + `v4` | `hdpi` → `ldpi`, `v4` → stripped | `ldpi/media/` |
605
+
606
+ The key principle: API-level qualifiers (`v<N>`) and a few others (layout direction, screen shape, HDR, aspect) are **silently stripped**. Screen-size qualifiers (`sw<N>dp`, `w<N>dp`, `h<N>dp`, `small`/`normal`/`large`/`xlarge`) cause the **entire directory to be skipped** — resources are marked as "unmapped" in the report because HarmonyOS has no equivalent qualifier. This avoids incorrect conversions and keeps the output clean.
607
+
608
+ ---
609
+
610
+ ## Special Cases and Edge Cases
611
+
612
+ ### Multiple values files contributing to the same JSON
613
+
614
+ Android projects often have multiple XML files under `values/` that all contain `<string>` or `<color>` entries. For example:
615
+ - `values/strings.xml` — main strings
616
+ - `values/strings_feature.xml` — feature-specific strings
617
+ - `values/google_strings.xml` — library strings
618
+
619
+ All `<string>` entries from any file go into a single `string.json`. Similarly for colors, dimens, etc. Collect entries across all files before writing.
620
+
621
+ ### Resource name conflicts
622
+
623
+ If two files define the same resource name, the last one wins (matching Android's behavior where later entries override earlier ones). Log these conflicts in the report.
624
+
625
+ ### Android resource references
626
+
627
+ Android values may reference other resources: `@string/other_string`, `@color/primary`, `@dimen/margin`. These references don't have a direct equivalent in HarmonyOS element JSON. Convert them as:
628
+ - `@string/name` → `$string:name`
629
+ - `@color/name` → `$color:name`
630
+ - `@dimen/name` → `$float:name`
631
+ - `@integer/name` → `$integer:name`
632
+ - `@bool/name` → `$boolean:name`
633
+ - `?attr/name` → log as unmappable (theme attribute reference)
634
+
635
+ ### Android system resource references
636
+
637
+ References like `@android:color/black` or `@android:string/ok` are Android system resources provided by the framework. These do NOT exist in HarmonyOS and MUST be resolved to concrete values during conversion — they cannot be left as `@android:` references in the output.
638
+
639
+ **Resolution rules:**
640
+ - `@android:color/*` — resolve using the built-in Android system color lookup table (see SKILL.md Step 5.2 for the complete table). Common examples: `@android:color/white` → `#ffffffff`, `@android:color/black` → `#ff000000`, `@android:color/transparent` → `#00000000`.
641
+ - `@android:dimen/*` — resolve using the built-in system dimension lookup table (see SKILL.md Step 5.2).
642
+ - `@android:string/*` — resolve to the known English string value. Common: `@android:string/ok` → `"OK"`, `@android:string/cancel` → `"Cancel"`.
643
+ - `@android:integer/*` — resolve to the known integer value.
644
+ - For any `@android:type/name` not found in the lookup tables, log a warning in the report and substitute a type-appropriate default (colors → `#ff000000`, dimens → `0vp`, integers → `0`, strings → `""`).
645
+ - When converting from a decompiled APK, the framework resource values can also be found in the decompiled output — use those as a secondary source.
646
+
647
+ **NEVER leave `@android:` references in the final HarmonyOS output.** They will cause compilation errors since HarmonyOS has no concept of Android system resources.
648
+
649
+ ### Empty or comment-only XML files
650
+
651
+ Skip these silently — don't create empty JSON files.
652
+
653
+ ### Large resource sets
654
+
655
+ When an Android project has hundreds of resources, process them systematically:
656
+ 1. First scan and inventory all resources
657
+ 2. Group by type and qualifier
658
+ 3. Convert each group
659
+ 4. Verify completeness
660
+
661
+ ### XML encoding and BOM
662
+
663
+ Some Android XML files may have BOM (Byte Order Mark) or non-UTF-8 encoding declarations. Handle these gracefully — read with the declared encoding, output UTF-8 JSON.