@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,513 @@
1
+ # Android XML Drawable to SVG Conversion Rules
2
+
3
+ This document provides complete rules for converting Android XML drawable resources to SVG format for HarmonyOS. HarmonyOS natively supports SVG in `media/` directories, making SVG the ideal target format for XML drawables that would otherwise be lost in migration.
4
+
5
+ ## Table of Contents
6
+ 1. [General Principles](#general-principles)
7
+ 2. [VectorDrawable Conversion](#vectordrawable-conversion)
8
+ 3. [ShapeDrawable Conversion](#shapedrawable-conversion)
9
+ 4. [LayerList Conversion](#layerlist-conversion)
10
+ 5. [Selector / StateList Conversion](#selector--statelist-conversion)
11
+ 6. [Gradient Conversion](#gradient-conversion)
12
+ 7. [Common Attribute Mapping](#common-attribute-mapping)
13
+ 8. [Unconvertible Types](#unconvertible-types)
14
+
15
+ ---
16
+
17
+ ## General Principles
18
+
19
+ - Output files use the original Android filename with `.svg` extension (e.g., `ic_arrow.xml` → `ic_arrow.svg`)
20
+ - All SVG output should use the SVG 1.1 namespace: `xmlns="http://www.w3.org/2000/svg"`
21
+ - Android uses `dp` units for dimensions; convert to unitless numbers in SVG (1dp = 1 SVG user unit)
22
+ - Android colors use `#AARRGGBB` or `#RRGGBB`; SVG uses `#RRGGBB` with a separate `opacity` or `fill-opacity` attribute for alpha
23
+ - When a drawable XML references another resource (`@drawable/other`, `@color/primary`), resolve the reference if possible. If not resolvable, use a reasonable default and log it in the report.
24
+
25
+ ### Color Conversion (Android → SVG)
26
+
27
+ | Android Format | SVG Fill/Stroke | SVG Opacity |
28
+ |---|---|---|
29
+ | `#RRGGBB` | `#RRGGBB` | (none, fully opaque) |
30
+ | `#AARRGGBB` | `#RRGGBB` | `opacity="AA/255"` as decimal (e.g., `#80FF0000` → `fill="#FF0000" fill-opacity="0.502"`) |
31
+ | `#RGB` | Expand to `#RRGGBB` | (none) |
32
+ | `#ARGB` | Expand to `#RRGGBB` | Extract alpha as decimal |
33
+
34
+ ### Dimension Conversion
35
+
36
+ - `24dp` → `24` (strip `dp` suffix, use as unitless SVG user units)
37
+ - `@dimen/ref` → resolve from dimens.xml if available, otherwise use a default and log
38
+
39
+ ---
40
+
41
+ ## VectorDrawable Conversion
42
+
43
+ Android VectorDrawable (`<vector>`) is structurally very similar to SVG. This is the most straightforward conversion.
44
+
45
+ ### Android VectorDrawable Example
46
+
47
+ ```xml
48
+ <vector xmlns:android="http://schemas.android.com/apk/res/android"
49
+ android:width="24dp"
50
+ android:height="24dp"
51
+ android:viewportWidth="24"
52
+ android:viewportHeight="24"
53
+ android:tint="#FF000000"
54
+ android:alpha="0.8">
55
+ <group
56
+ android:name="arrow_group"
57
+ android:rotation="90"
58
+ android:pivotX="12"
59
+ android:pivotY="12"
60
+ android:scaleX="1.5"
61
+ android:scaleY="1.5"
62
+ android:translateX="2"
63
+ android:translateY="0">
64
+ <path
65
+ android:name="arrow"
66
+ android:pathData="M12,2L4.5,20.29l0.71,0.71L12,18l6.79,3 0.71,-0.71z"
67
+ android:fillColor="#FF4081"
68
+ android:fillAlpha="0.8"
69
+ android:strokeColor="#000000"
70
+ android:strokeWidth="1"
71
+ android:strokeAlpha="1"
72
+ android:strokeLineCap="round"
73
+ android:strokeLineJoin="round"
74
+ android:fillType="evenOdd"
75
+ android:trimPathStart="0"
76
+ android:trimPathEnd="1" />
77
+ <clip-path
78
+ android:name="clip"
79
+ android:pathData="M0,0h24v24H0z" />
80
+ </group>
81
+ </vector>
82
+ ```
83
+
84
+ ### Converted SVG Output
85
+
86
+ ```svg
87
+ <svg xmlns="http://www.w3.org/2000/svg"
88
+ width="24" height="24"
89
+ viewBox="0 0 24 24"
90
+ opacity="0.8">
91
+ <g transform="translate(2,0) scale(1.5,1.5) rotate(90,12,12)">
92
+ <defs>
93
+ <clipPath id="clip">
94
+ <path d="M0,0h24v24H0z"/>
95
+ </clipPath>
96
+ </defs>
97
+ <path d="M12,2L4.5,20.29l0.71,0.71L12,18l6.79,3 0.71,-0.71z"
98
+ fill="#FF4081" fill-opacity="0.8"
99
+ stroke="#000000" stroke-width="1"
100
+ stroke-linecap="round" stroke-linejoin="round"
101
+ fill-rule="evenodd"
102
+ clip-path="url(#clip)"/>
103
+ </g>
104
+ </svg>
105
+ ```
106
+
107
+ ### Element Mapping: `<vector>` → `<svg>`
108
+
109
+ | Android Attribute | SVG Equivalent |
110
+ |---|---|
111
+ | `android:width` | `width` (strip `dp`) |
112
+ | `android:height` | `height` (strip `dp`) |
113
+ | `android:viewportWidth` | Part of `viewBox="0 0 W H"` |
114
+ | `android:viewportHeight` | Part of `viewBox="0 0 W H"` |
115
+ | `android:alpha` | `opacity` on root `<svg>` |
116
+ | `android:tint` | Apply as a filter or ignore (SVG has no direct tint; log in report) |
117
+
118
+ ### Element Mapping: `<path>` → `<path>`
119
+
120
+ | Android Attribute | SVG Attribute |
121
+ |---|---|
122
+ | `android:pathData` | `d` (path data syntax is identical) |
123
+ | `android:fillColor` | `fill` (convert color format) |
124
+ | `android:fillAlpha` | `fill-opacity` |
125
+ | `android:strokeColor` | `stroke` (convert color format) |
126
+ | `android:strokeWidth` | `stroke-width` |
127
+ | `android:strokeAlpha` | `stroke-opacity` |
128
+ | `android:strokeLineCap` | `stroke-linecap` (`butt`, `round`, `square`) |
129
+ | `android:strokeLineJoin` | `stroke-linejoin` (`miter`, `round`, `bevel`) |
130
+ | `android:strokeMiterLimit` | `stroke-miterlimit` |
131
+ | `android:fillType` | `fill-rule` (`nonZero` → `nonzero`, `evenOdd` → `evenodd`) |
132
+ | `android:trimPathStart` | No direct SVG equivalent; if != 0, use `stroke-dasharray` + `stroke-dashoffset` to approximate, or log |
133
+ | `android:trimPathEnd` | Same as above |
134
+ | `android:trimPathOffset` | Same as above |
135
+
136
+ ### Element Mapping: `<group>` → `<g>`
137
+
138
+ Build the SVG `transform` attribute from the group's transformation properties. Apply in this order:
139
+ 1. `translate(translateX, translateY)`
140
+ 2. `scale(scaleX, scaleY)`
141
+ 3. `rotate(rotation, pivotX, pivotY)`
142
+
143
+ Combined: `transform="translate(tX,tY) scale(sX,sY) rotate(r,pX,pY)"`
144
+
145
+ Only include transform components that differ from defaults (translate 0,0; scale 1,1; rotation 0).
146
+
147
+ ### Element Mapping: `<clip-path>` → `<clipPath>` + `<path>`
148
+
149
+ ```xml
150
+ <!-- Android -->
151
+ <clip-path android:pathData="M0,0h24v24H0z"/>
152
+
153
+ <!-- SVG -->
154
+ <defs>
155
+ <clipPath id="generated_clip_id">
156
+ <path d="M0,0h24v24H0z"/>
157
+ </clipPath>
158
+ </defs>
159
+ <!-- Apply via clip-path="url(#generated_clip_id)" on sibling paths -->
160
+ ```
161
+
162
+ Generate unique IDs for clip paths (e.g., `clip_1`, `clip_2`, or derive from `android:name`).
163
+
164
+ ---
165
+
166
+ ## ShapeDrawable Conversion
167
+
168
+ Android `<shape>` drawables define geometric shapes with fill, stroke, gradients, corners, and sizing.
169
+
170
+ ### Shape Types
171
+
172
+ #### Rectangle (default)
173
+
174
+ ```xml
175
+ <!-- Android -->
176
+ <shape xmlns:android="http://schemas.android.com/apk/res/android"
177
+ android:shape="rectangle">
178
+ <solid android:color="#FF4081"/>
179
+ <stroke android:width="2dp" android:color="#000000"
180
+ android:dashWidth="4dp" android:dashGap="2dp"/>
181
+ <corners android:radius="8dp"/>
182
+ <size android:width="100dp" android:height="50dp"/>
183
+ <padding android:left="10dp" android:top="5dp"
184
+ android:right="10dp" android:bottom="5dp"/>
185
+ </shape>
186
+ ```
187
+
188
+ ```svg
189
+ <!-- SVG -->
190
+ <svg xmlns="http://www.w3.org/2000/svg" width="100" height="50" viewBox="0 0 100 50">
191
+ <rect x="0" y="0" width="100" height="50" rx="8" ry="8"
192
+ fill="#FF4081"
193
+ stroke="#000000" stroke-width="2"
194
+ stroke-dasharray="4,2"/>
195
+ </svg>
196
+ ```
197
+
198
+ **Corner radius variants:**
199
+ - `android:radius` → `rx` and `ry` (same value)
200
+ - `android:topLeftRadius`, `android:topRightRadius`, `android:bottomRightRadius`, `android:bottomLeftRadius` → When different per corner, use a `<path>` with rounded corner arcs instead of `<rect>`
201
+
202
+ **Per-corner radius SVG path formula:**
203
+ ```
204
+ M {tlr},0
205
+ H {w-trr}
206
+ Q {w},0 {w},{trr}
207
+ V {h-brr}
208
+ Q {w},{h} {w-brr},{h}
209
+ H {blr}
210
+ Q 0,{h} 0,{h-blr}
211
+ V {tlr}
212
+ Q 0,0 {tlr},0
213
+ Z
214
+ ```
215
+ Where `tlr`=topLeftRadius, `trr`=topRightRadius, `brr`=bottomRightRadius, `blr`=bottomLeftRadius, `w`=width, `h`=height.
216
+
217
+ #### Oval
218
+
219
+ ```xml
220
+ <!-- Android -->
221
+ <shape android:shape="oval">
222
+ <solid android:color="#2196F3"/>
223
+ <size android:width="60dp" android:height="60dp"/>
224
+ </shape>
225
+ ```
226
+
227
+ ```svg
228
+ <!-- SVG -->
229
+ <svg xmlns="http://www.w3.org/2000/svg" width="60" height="60" viewBox="0 0 60 60">
230
+ <ellipse cx="30" cy="30" rx="30" ry="30" fill="#2196F3"/>
231
+ </svg>
232
+ ```
233
+
234
+ - If width == height, use `<circle>` instead: `<circle cx="30" cy="30" r="30"/>`
235
+
236
+ #### Line
237
+
238
+ ```xml
239
+ <!-- Android -->
240
+ <shape android:shape="line">
241
+ <stroke android:width="2dp" android:color="#000000"/>
242
+ <size android:height="2dp" android:width="100dp"/>
243
+ </shape>
244
+ ```
245
+
246
+ ```svg
247
+ <!-- SVG -->
248
+ <svg xmlns="http://www.w3.org/2000/svg" width="100" height="2" viewBox="0 0 100 2">
249
+ <line x1="0" y1="1" x2="100" y2="1" stroke="#000000" stroke-width="2"/>
250
+ </svg>
251
+ ```
252
+
253
+ #### Ring
254
+
255
+ ```xml
256
+ <!-- Android -->
257
+ <shape android:shape="ring"
258
+ android:innerRadius="20dp"
259
+ android:thickness="5dp">
260
+ <solid android:color="#4CAF50"/>
261
+ <size android:width="50dp" android:height="50dp"/>
262
+ </shape>
263
+ ```
264
+
265
+ ```svg
266
+ <!-- SVG -->
267
+ <svg xmlns="http://www.w3.org/2000/svg" width="50" height="50" viewBox="0 0 50 50">
268
+ <circle cx="25" cy="25" r="22.5"
269
+ fill="none" stroke="#4CAF50" stroke-width="5"/>
270
+ </svg>
271
+ ```
272
+
273
+ - Ring center radius = `innerRadius + thickness/2`
274
+ - SVG stroke-width = `thickness`
275
+ - If `android:innerRadiusRatio` is used instead of `android:innerRadius`: `innerRadius = width / (2 * innerRadiusRatio)`
276
+ - If `android:thicknessRatio` is used: `thickness = width / (2 * thicknessRatio)`
277
+
278
+ ### Shape Size Handling
279
+
280
+ If `<size>` is not specified, use a sensible default (e.g., `24x24`) and note in the report that the original had no explicit size. The SVG `viewBox` should match the dimensions.
281
+
282
+ ---
283
+
284
+ ## Gradient Conversion
285
+
286
+ Android shapes and vector drawables can use gradients for fill or stroke colors.
287
+
288
+ ### Linear Gradient
289
+
290
+ ```xml
291
+ <!-- Android (in shape) -->
292
+ <gradient
293
+ android:type="linear"
294
+ android:startColor="#FF0000"
295
+ android:centerColor="#00FF00"
296
+ android:endColor="#0000FF"
297
+ android:angle="45"/>
298
+ ```
299
+
300
+ ```svg
301
+ <!-- SVG -->
302
+ <defs>
303
+ <linearGradient id="grad_1" x1="0%" y1="100%" x2="100%" y2="0%">
304
+ <stop offset="0%" stop-color="#FF0000"/>
305
+ <stop offset="50%" stop-color="#00FF00"/>
306
+ <stop offset="100%" stop-color="#0000FF"/>
307
+ </linearGradient>
308
+ </defs>
309
+ <rect ... fill="url(#grad_1)"/>
310
+ ```
311
+
312
+ **Angle to coordinates mapping:**
313
+
314
+ | Android `angle` | SVG `x1,y1 → x2,y2` |
315
+ |---|---|
316
+ | 0 (left→right) | `0%,0% → 100%,0%` |
317
+ | 45 (bottom-left→top-right) | `0%,100% → 100%,0%` |
318
+ | 90 (bottom→top) | `0%,100% → 0%,0%` |
319
+ | 135 (bottom-right→top-left) | `100%,100% → 0%,0%` |
320
+ | 180 (right→left) | `100%,0% → 0%,0%` |
321
+ | 225 (top-right→bottom-left) | `100%,0% → 0%,100%` |
322
+ | 270 (top→bottom) | `0%,0% → 0%,100%` |
323
+ | 315 (top-left→bottom-right) | `0%,0% → 100%,100%` |
324
+
325
+ Android `angle` must be a multiple of 45. For other values, calculate:
326
+ - `x1 = 50 + 50*cos(angle+180)`, `y1 = 50 - 50*sin(angle+180)`
327
+ - `x2 = 50 + 50*cos(angle)`, `y2 = 50 - 50*sin(angle)`
328
+
329
+ ### Radial Gradient
330
+
331
+ ```xml
332
+ <!-- Android -->
333
+ <gradient
334
+ android:type="radial"
335
+ android:centerX="0.5"
336
+ android:centerY="0.5"
337
+ android:gradientRadius="50%p"
338
+ android:startColor="#FFFFFF"
339
+ android:endColor="#000000"/>
340
+ ```
341
+
342
+ ```svg
343
+ <!-- SVG -->
344
+ <defs>
345
+ <radialGradient id="grad_2" cx="50%" cy="50%" r="50%">
346
+ <stop offset="0%" stop-color="#FFFFFF"/>
347
+ <stop offset="100%" stop-color="#000000"/>
348
+ </radialGradient>
349
+ </defs>
350
+ ```
351
+
352
+ - `centerX`/`centerY` are fractions (0.0–1.0) → convert to percentages
353
+ - `gradientRadius` with `%p` suffix → percentage of parent dimension
354
+
355
+ ### Sweep Gradient
356
+
357
+ ```xml
358
+ <!-- Android -->
359
+ <gradient
360
+ android:type="sweep"
361
+ android:centerX="0.5"
362
+ android:centerY="0.5"
363
+ android:startColor="#FF0000"
364
+ android:endColor="#0000FF"/>
365
+ ```
366
+
367
+ SVG doesn't have a native sweep/conic gradient in SVG 1.1. Options:
368
+ 1. Use CSS `conic-gradient` if targeting modern renderers (but not SVG 1.1 compliant)
369
+ 2. Approximate with a series of `<path>` segments in a radial pattern
370
+ 3. Log as partially converted and note that sweep gradient was approximated
371
+
372
+ Recommended: convert to a `<linearGradient>` as an approximation and log in the report that the original was a sweep gradient.
373
+
374
+ ### Gradient in VectorDrawable Paths
375
+
376
+ Android API 24+ supports `<aapt:attr>` inline gradient in vector drawables:
377
+
378
+ ```xml
379
+ <path android:pathData="...">
380
+ <aapt:attr name="android:fillColor">
381
+ <gradient android:type="linear" .../>
382
+ </aapt:attr>
383
+ </path>
384
+ ```
385
+
386
+ Convert the gradient to an SVG `<linearGradient>` in `<defs>` and reference via `fill="url(#grad_id)"`.
387
+
388
+ ---
389
+
390
+ ## LayerList Conversion
391
+
392
+ `<layer-list>` stacks multiple drawable items. Each `<item>` can contain a `<shape>`, a `<bitmap>`, or reference another drawable.
393
+
394
+ ```xml
395
+ <!-- Android -->
396
+ <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
397
+ <item>
398
+ <shape android:shape="rectangle">
399
+ <solid android:color="#CCCCCC"/>
400
+ <corners android:radius="4dp"/>
401
+ </shape>
402
+ </item>
403
+ <item android:left="2dp" android:top="2dp"
404
+ android:right="2dp" android:bottom="2dp">
405
+ <shape android:shape="rectangle">
406
+ <solid android:color="#FFFFFF"/>
407
+ <corners android:radius="2dp"/>
408
+ </shape>
409
+ </item>
410
+ </layer-list>
411
+ ```
412
+
413
+ ```svg
414
+ <!-- SVG -->
415
+ <svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100">
416
+ <!-- Layer 0: background -->
417
+ <rect x="0" y="0" width="100" height="100" rx="4" ry="4" fill="#CCCCCC"/>
418
+ <!-- Layer 1: foreground with insets -->
419
+ <rect x="2" y="2" width="96" height="96" rx="2" ry="2" fill="#FFFFFF"/>
420
+ </svg>
421
+ ```
422
+
423
+ ### Rules
424
+
425
+ - Items are rendered in document order (first item = bottom layer)
426
+ - `android:left/top/right/bottom` on `<item>` → inset the element's position and reduce its size accordingly
427
+ - `android:width/height` on `<item>` → explicit size override
428
+ - `android:gravity` on `<item>` → position within the layer bounds
429
+ - If an `<item>` references another drawable via `android:drawable="@drawable/other"`, try to resolve and inline it; if not resolvable, log in report
430
+ - For layer-lists without explicit `<size>`, use a default canvas of `100x100` and note in report
431
+
432
+ ---
433
+
434
+ ## Selector / StateList Conversion
435
+
436
+ `<selector>` defines different drawables for different UI states (pressed, focused, disabled, etc.). SVG is static, so we extract the most useful representation.
437
+
438
+ ```xml
439
+ <!-- Android -->
440
+ <selector xmlns:android="http://schemas.android.com/apk/res/android">
441
+ <item android:state_pressed="true">
442
+ <shape android:shape="rectangle">
443
+ <solid android:color="#E0E0E0"/>
444
+ <corners android:radius="4dp"/>
445
+ </shape>
446
+ </item>
447
+ <item android:state_focused="true">
448
+ <shape android:shape="rectangle">
449
+ <solid android:color="#F0F0F0"/>
450
+ <corners android:radius="4dp"/>
451
+ </shape>
452
+ </item>
453
+ <item>
454
+ <shape android:shape="rectangle">
455
+ <solid android:color="#FFFFFF"/>
456
+ <corners android:radius="4dp"/>
457
+ </shape>
458
+ </item>
459
+ </selector>
460
+ ```
461
+
462
+ ### Conversion Strategy
463
+
464
+ 1. Find the **default item** — the `<item>` with no `android:state_*` attributes (or the last item, which serves as the default in Android)
465
+ 2. Convert that single item to SVG using the appropriate rules (shape → SVG, vector → SVG, etc.)
466
+ 3. In the conversion report, list all the state variants that were dropped:
467
+ - `state_pressed`, `state_focused`, `state_selected`, `state_checked`, `state_enabled`, `state_activated`, `state_hovered`
468
+ 4. Note that HarmonyOS state handling should be done in ArkUI component code, not in resource files
469
+
470
+ ---
471
+
472
+ ## Common Attribute Mapping
473
+
474
+ ### Android `android:` namespace to SVG
475
+
476
+ | Android Attribute | SVG Equivalent | Notes |
477
+ |---|---|---|
478
+ | `android:fillColor` | `fill` | Convert color format |
479
+ | `android:strokeColor` | `stroke` | Convert color format |
480
+ | `android:strokeWidth` | `stroke-width` | Strip `dp` |
481
+ | `android:alpha` | `opacity` | 0.0-1.0 range |
482
+ | `android:fillAlpha` | `fill-opacity` | 0.0-1.0 range |
483
+ | `android:strokeAlpha` | `stroke-opacity` | 0.0-1.0 range |
484
+ | `android:rotation` | `transform="rotate(deg)"` | In `<group>` |
485
+ | `android:scaleX/Y` | `transform="scale(x,y)"` | In `<group>` |
486
+ | `android:translateX/Y` | `transform="translate(x,y)"` | In `<group>` |
487
+
488
+ ### Default Values
489
+
490
+ If an Android drawable doesn't specify certain attributes, use these defaults:
491
+ - `fillColor`: `#000000` (black) for paths in `<vector>`, transparent for shapes without `<solid>`
492
+ - `strokeWidth`: `0` (no stroke)
493
+ - `alpha`: `1.0`
494
+ - `fillType`: `nonZero`
495
+
496
+ ---
497
+
498
+ ## Unconvertible Types
499
+
500
+ These XML drawable types cannot be meaningfully converted to SVG and should be logged as unmappable in the conversion report:
501
+
502
+ | Type | Root Element | Reason |
503
+ |---|---|---|
504
+ | Ripple | `<ripple>` | Runtime touch feedback animation |
505
+ | Animated Vector | `<animated-vector>` | Requires animation timing/interpolation |
506
+ | Animated Selector | `<animated-selector>` | State transitions with animations |
507
+ | Transition Drawable | `<transition>` | Cross-fade between two drawables |
508
+ | Inset Drawable | `<inset>` | Simple wrapper; if inner drawable is convertible, convert that instead |
509
+ | Scale Drawable | `<scale>` | Runtime scaling behavior |
510
+ | Rotate Drawable | `<rotate>` | Runtime rotation; could be converted as static rotation if angle is fixed |
511
+ | Level List | `<level-list>` | Runtime level-based selection |
512
+
513
+ For `<inset>` and `<rotate>` with fixed values, attempt conversion by applying the inset/rotation statically and convert the inner drawable. Log in the report either way.
@@ -0,0 +1,10 @@
1
+ {
2
+ "app": {
3
+ "bundleName": "com.example.myapplication",
4
+ "vendor": "example",
5
+ "versionCode": 1000000,
6
+ "versionName": "1.0.0",
7
+ "icon": "$media:layered_image",
8
+ "label": "$string:app_name"
9
+ }
10
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "string": [
3
+ {
4
+ "name": "app_name",
5
+ "value": "MyApplication"
6
+ }
7
+ ]
8
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "layered-image":
3
+ {
4
+ "background" : "$media:background",
5
+ "foreground" : "$media:foreground"
6
+ }
7
+ }
@@ -0,0 +1,42 @@
1
+ {
2
+ "app": {
3
+ "signingConfigs": [],
4
+ "products": [
5
+ {
6
+ "name": "default",
7
+ "signingConfig": "default",
8
+ "targetSdkVersion": "6.0.2(22)",
9
+ "compatibleSdkVersion": "6.0.2(22)",
10
+ "runtimeOS": "HarmonyOS",
11
+ "buildOption": {
12
+ "strictMode": {
13
+ "caseSensitiveCheck": true,
14
+ "useNormalizedOHMUrl": true
15
+ }
16
+ }
17
+ }
18
+ ],
19
+ "buildModeSet": [
20
+ {
21
+ "name": "debug",
22
+ },
23
+ {
24
+ "name": "release"
25
+ }
26
+ ]
27
+ },
28
+ "modules": [
29
+ {
30
+ "name": "entry",
31
+ "srcPath": "./entry",
32
+ "targets": [
33
+ {
34
+ "name": "default",
35
+ "applyToProducts": [
36
+ "default"
37
+ ]
38
+ }
39
+ ]
40
+ }
41
+ ]
42
+ }
@@ -0,0 +1,32 @@
1
+ {
2
+ "files": [
3
+ "**/*.ets"
4
+ ],
5
+ "ignore": [
6
+ "**/src/ohosTest/**/*",
7
+ "**/src/test/**/*",
8
+ "**/src/mock/**/*",
9
+ "**/node_modules/**/*",
10
+ "**/oh_modules/**/*",
11
+ "**/build/**/*",
12
+ "**/.preview/**/*"
13
+ ],
14
+ "ruleSet": [
15
+ "plugin:@performance/recommended",
16
+ "plugin:@typescript-eslint/recommended"
17
+ ],
18
+ "rules": {
19
+ "@security/no-unsafe-aes": "error",
20
+ "@security/no-unsafe-hash": "error",
21
+ "@security/no-unsafe-mac": "warn",
22
+ "@security/no-unsafe-dh": "error",
23
+ "@security/no-unsafe-dsa": "error",
24
+ "@security/no-unsafe-ecdsa": "error",
25
+ "@security/no-unsafe-rsa-encrypt": "error",
26
+ "@security/no-unsafe-rsa-sign": "error",
27
+ "@security/no-unsafe-rsa-key": "error",
28
+ "@security/no-unsafe-dsa-key": "error",
29
+ "@security/no-unsafe-dh-key": "error",
30
+ "@security/no-unsafe-3des": "error"
31
+ }
32
+ }
@@ -0,0 +1,33 @@
1
+ {
2
+ "apiType": "stageMode",
3
+ "buildOption": {
4
+ "resOptions": {
5
+ "copyCodeResource": {
6
+ "enable": false
7
+ }
8
+ }
9
+ },
10
+ "buildOptionSet": [
11
+ {
12
+ "name": "release",
13
+ "arkOptions": {
14
+ "obfuscation": {
15
+ "ruleOptions": {
16
+ "enable": false,
17
+ "files": [
18
+ "./obfuscation-rules.txt"
19
+ ]
20
+ }
21
+ }
22
+ }
23
+ },
24
+ ],
25
+ "targets": [
26
+ {
27
+ "name": "default"
28
+ },
29
+ {
30
+ "name": "ohosTest",
31
+ }
32
+ ]
33
+ }
@@ -0,0 +1,6 @@
1
+ import { hapTasks } from '@ohos/hvigor-ohos-plugin';
2
+
3
+ export default {
4
+ system: hapTasks, /* Built-in plugin of Hvigor. It cannot be modified. */
5
+ plugins: [] /* Custom plugin to extend the functionality of Hvigor. */
6
+ }
@@ -0,0 +1,23 @@
1
+ # Define project specific obfuscation rules here.
2
+ # You can include the obfuscation configuration files in the current module's build-profile.json5.
3
+ #
4
+ # For more details, see
5
+ # https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/source-obfuscation
6
+
7
+ # Obfuscation options:
8
+ # -disable-obfuscation: disable all obfuscations
9
+ # -enable-property-obfuscation: obfuscate the property names
10
+ # -enable-toplevel-obfuscation: obfuscate the names in the global scope
11
+ # -compact: remove unnecessary blank spaces and all line feeds
12
+ # -remove-log: remove all console.* statements
13
+ # -print-namecache: print the name cache that contains the mapping from the old names to new names
14
+ # -apply-namecache: reuse the given cache file
15
+
16
+ # Keep options:
17
+ # -keep-property-name: specifies property names that you want to keep
18
+ # -keep-global-name: specifies names that you want to keep in the global scope
19
+
20
+ -enable-property-obfuscation
21
+ -enable-toplevel-obfuscation
22
+ -enable-filename-obfuscation
23
+ -enable-export-obfuscation