{"id":30138798,"url":"https://github.com/irgaly/compose-vector-plugin","last_synced_at":"2025-08-11T02:03:01.897Z","repository":{"id":245665629,"uuid":"818904051","full_name":"irgaly/compose-vector-plugin","owner":"irgaly","description":"Gradle Plugin for Converting SVG file to Compose ImageVector","archived":false,"fork":false,"pushed_at":"2025-07-15T06:09:22.000Z","size":475,"stargazers_count":36,"open_issues_count":1,"forks_count":2,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-08-10T04:34:12.214Z","etag":null,"topics":["android","compose","gradle","gradle-plugin","kotlin"],"latest_commit_sha":null,"homepage":"https://plugins.gradle.org/plugin/io.github.irgaly.compose-vector","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/irgaly.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":"irgaly","custom":["https://github.com/irgaly/irgaly"]}},"created_at":"2024-06-23T07:58:13.000Z","updated_at":"2025-08-01T01:22:28.000Z","dependencies_parsed_at":"2024-06-23T09:23:36.878Z","dependency_job_id":"ded05cea-3087-4d58-a418-6efbddaa4a4d","html_url":"https://github.com/irgaly/compose-vector-plugin","commit_stats":null,"previous_names":["irgaly/compose-vector-plugin"],"tags_count":5,"template":false,"template_full_name":"irgaly/android-gradle-plugin-template","purl":"pkg:github/irgaly/compose-vector-plugin","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/irgaly%2Fcompose-vector-plugin","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/irgaly%2Fcompose-vector-plugin/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/irgaly%2Fcompose-vector-plugin/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/irgaly%2Fcompose-vector-plugin/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/irgaly","download_url":"https://codeload.github.com/irgaly/compose-vector-plugin/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/irgaly%2Fcompose-vector-plugin/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":269819012,"owners_count":24480086,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-11T02:00:10.019Z","response_time":75,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android","compose","gradle","gradle-plugin","kotlin"],"created_at":"2025-08-11T02:01:35.342Z","updated_at":"2025-08-11T02:03:01.861Z","avatar_url":"https://github.com/irgaly.png","language":"Kotlin","funding_links":["https://github.com/sponsors/irgaly","https://github.com/irgaly/irgaly"],"categories":[],"sub_categories":[],"readme":"# Gradle Compose Vector Plugin\n\nGradle Plugin for Converting SVG file to [Compose ImageVector](https://developer.android.com/reference/kotlin/androidx/compose/ui/graphics/vector/ImageVector).\n\nThis plugin supports:\n\n* Kotlin Multiplatform Project (KMP).\n* Android Project.\n* Gradle Incremental Build for converting SVG to ImageVector.\n\n## Usage\n\nApply this plugin to your KMP project or Android Project.\n\n`app/build.gradle.kts`\n\n```kotlin\nplugins {\n    // For example, Android Application Project\n    id(\"org.jetbrains.kotlin.android\")\n    id(\"com.android.application\")\n    // or Android Library Project\n    //id(\"com.android.library\")\n    //id(\"com.android.kotlin.multiplatform.library\")\n    // or KMP Project\n    //id(\"org.jetbrains.kotlin.multiplatform\")\n\n    // Apply Compose Vector Plugin\n    id(\"io.github.irgaly.compose-vector\") version \"1.1.0\"\n}\n...\n```\n\nConfigure plugin with `composeVector` extension.\n\n`app/build.gradle.kts`\n\n```kotlin\ncomposeVector {\n    // This is a required configuration.\n    // The destination package that ImageVector Images will place to.\n    packageName = \"io.github.irgaly.compose.vector.sample.image\"\n\n    // This is an optional configuration.\n    // The directory that SVG files are placed.\n    // Default value is \"{project directory}/images\"\n    inputDir = layout.projectDirectory.dir(\"images\")\n}\n```\n\nThen put your SVG files to `inputDir`.\n\n`{project directory}/images` directory is default location.\n\n![SVG images in {project directory}/images](docs/inputdir_images.png)\n\nRun `generateImageVector` task for generating ImageVector classes.\n\nOr `KotlinCompile Task` will trigger generateImageVector task by tasks dependency.\n\n```shell\n# run generateImageVector\n% ./gradlew :app:generateImageVector\n\n# or compile task\n% ./gradlew :app:compileDebugKotlin\n...\n\u003e Task :app:generateImageVector UP-TO-DATE\n...\n\u003e Task :app:compileDebugKotlin\n...\n```\n\nThe ImageVector classes will be placed to under `build/compose-vector` directory by default.\n\n![ImageVector classes in {build directory}](docs/output_imagevectors.png)\n\nThe outputDir under `build` directory is registered to SourceSet by default,\nso generated ImageVector classes can be used from your project.\n\n```kotlin\n...\nimport io.github.irgaly.compose.vector.sample.image.Icons\nimport io.github.irgaly.compose.vector.sample.image.icons.automirrored.filled.Undo\nimport io.github.irgaly.compose.vector.sample.image.icons.filled.Undo\n...\n    MaterialTheme {\n        Column(Modifier.fillMaxSize()) {\n            Image(Icons.Filled.Undo, contentDescription = null)\n            Image(Icons.AutoMirrored.Filled.Undo, contentDescription = null)\n        }\n    }\n```\n\nThe generated ImageVector property will be something like this:\n\n```kotlin\n...\n@Suppress(\"RedundantVisibilityModifier\")\npublic val Icons.Filled.Undo: ImageVector\n    get() {\n        if (_undo != null) {\n            return _undo!!\n        }\n        _undo = Builder(\"Undo\", 24.dp, 24.dp, 960f, 960f).apply {\n            group(translationY = 960f) {\n                val fill0 = SolidColor(Color(0xFFE8EAED))\n                val fillAlpha0 = 1f\n                val strokeAlpha0 = 1f\n                val strokeLineWidth0 = 1f\n                val strokeLineCap0 = StrokeCap.Butt\n                val strokeLineJoin0 = StrokeJoin.Miter\n                val strokeLineMiter0 = 4f\n                path(fill = fill0, fillAlpha = fillAlpha0, strokeAlpha = strokeAlpha0,\n                        strokeLineWidth = strokeLineWidth0, strokeLineCap = strokeLineCap0,\n                        strokeLineJoin = strokeLineJoin0, strokeLineMiter = strokeLineMiter0) {\n                    moveTo(280f, -200f)\n                    verticalLineToRelative(-80f)\n                    horizontalLineToRelative(284f)\n                    quadToRelative(63f, 0f, 109.5f, -40f)\n                    reflectiveQuadTo(720f, -420f)\n                    quadToRelative(0f, -60f, -46.5f, -100f)\n                    reflectiveQuadTo(564f, -560f)\n                    horizontalLineTo(312f)\n                    lineToRelative(104f, 104f)\n                    lineToRelative(-56f, 56f)\n                    lineToRelative(-200f, -200f)\n                    lineToRelative(200f, -200f)\n                    lineToRelative(56f, 56f)\n                    lineToRelative(-104f, 104f)\n                    horizontalLineToRelative(252f)\n                    quadToRelative(97f, 0f, 166.5f, 63f)\n                    reflectiveQuadTo(800f, -420f)\n                    quadToRelative(0f, 94f, -69.5f, 157f)\n                    reflectiveQuadTo(564f, -200f)\n                    horizontalLineTo(280f)\n                    close()\n                }\n            }\n        }.build()\n        return _undo!!\n    }\n\nprivate var _undo: ImageVector? = null\n\n@Preview\n@Composable\nprivate fun UndoPreview() {\n    Image(Icons.Filled.Undo, null)\n}\n\n@Preview(showBackground = true)\n@Composable\nprivate fun UndoBackgroundPreview() {\n    Image(Icons.Filled.Undo, null)\n}\n```\n\n## ImageVector properties structure\n\nThe input directories structure will be mapped to ImageVector properties structure.\n\nFor example:\n\n```\nimages\n└── icons\n    ├── automirrored\n    │   └── filled\n    │       └── undo.svg\n    └── filled\n        └── undo.svg\n```\n\nThis produces two ImageVector properties:\n\n* `Icons.AutoMirrored.Filled.Undo: ImageVector`\n* `Icons.Filled.Undo: ImageVector`\n\nThe first directory's name `icons` will be root Object Class name `Icons`.\nThe other directories will be used as package names.\nSVG file names will be used as ImageVector property names.\n\n## Name Conversion\n\nThe package name is same as input directory names.\n\nThe receiver classes and the ImageVector property names will converted by drop Ascii Symbols, then converted from snake cases to camel cases.\nIn special case, the `automirrored` package name will be `AutoMirrored` receiver class.\n\nName conversion example:\n\n* undo.svg -\u003e `Undo` property\n* vector_image.svg -\u003e `VectorImage` property\n* 0_image.svg -\u003e `Image` property\n* _my_icon.svg -\u003e `MyIcon` property\n* my_icon_.svg -\u003e `MyIcon` property\n* my_icon_0.svg -\u003e `MyIcon0` property\n* 0_my_icon.svg -\u003e `_0MyIcon` property\n* MyIcon.svg -\u003e `MyIcon` property\n* MySVGIcon.svg -\u003e `MySVGIcon` property\n\nIf you want to apply custom name conversion rule, please use `composeVector` extension's transformer options.\n\n## Support AutoMirrored ImageVector\n\nThe `automirrored` package name is a special name.\n\nThe ImageVector classes under `automirrored` package or sub packages will be exported with [autoMirror = true](https://developer.android.com/reference/kotlin/androidx/compose/ui/graphics/vector/ImageVector#autoMirror()).\n\n```kotlin\npublic val Icons.AutoMirrored.Filled.Undo: ImageVector\n    get() {\n        if (_undo != null) {\n            return _undo!!\n        }\n        _undo = Builder(\"Undo\", 24.dp, 24.dp, 960f, 960f, autoMirror = true).apply {\n            ...\n```\n\n## Project type and SourceSets\n\nIf the output directory is under the project's `build` directory, The output directory will be registered to SourceSets.\n\n| Project type          | composeVector configuration                      | registered SourceSets   |\n|-----------------------|--------------------------------------------------|-------------------------|\n| KMP project           | multiplatformGenerationTarget = Common (Default) | Common Main SourceSets  |\n| KMP + Android project | multiplatformGenerationTarget = Android          | Android Main SourceSets |\n| Android project       | -                                                | Android Main SourceSets |\n\n## composeVector Extension options\n\n`build.gradle.kts`\n\n```kotlin\nimport io.github.irgaly.compose.vector.plugin.ComposeVectorExtension\n\n...\n\ncomposeVector {\n    // ImageVector classes destination package name\n    // \n    // Required\n    packagenName = \"your.package.name\"\n\n    // Vector files directory\n    //\n    // Optional\n    // Default: {project directory}/images\n    inputDir = layout.projectDirectory.dir(\"images\")\n    \n    // Generated Kotlin Sources directory.\n    // outputDir is registered to SourceSet when outputDir is inside of project's buildDirectory.\n    //\n    // Optional\n    // Default: {build directory}/compose-vector/src/main/kotlin\n    outputDir = layout.buildDirectory.dir(\"compose-vector/src/main/kotlin\")\n    \n    // Custom preconverter logic to ImageVector property names and receiver class names.\n    //\n    // * args\n    //   * File: source file or directory's File instance\n    //   * String: source file or directory's name\n    //\n    // Optional\n    preClassNameTransformer.set (org.gradle.api.Transformer { (file: File, name: String) -\u003e\n        // custom logic here\n        \"pre_transformed_class_name\"\n    })\n\n    // Custom postconverter logic to ImageVector property names and receiver class names.\n    //\n    // * args\n    //   * File: source file or directory's File instance\n    //   * String: transformed name\n    //\n    // Optional\n    postClassNameTransformer.set (org.gradle.api.Transformer { (file: File, name: String) -\u003e\n        // custom logic here\n        \"transformed_class_name\"\n    })\n\n    // Custom converter logic to package names.\n    //\n    // * args\n    //   * File: source directory's File instance\n    //   * String: source directory's name\n    //\n    // Optional\n    packageNameTransformer.set (org.gradle.api.Transformer { (file: File, name: String) -\u003e\n        // custom logic here\n        \"transformed_package_name\"\n    })\n    \n    // Target SourceSets that generated images belongs to for KMP project.\n    // This option is affect to KMP Project, not to Android only Project.\n    //\n    // Optional\n    // Default: ComposeVectorExtension.GenerationTarget.Common\n    multiplatformGenerationTarget = ComposeVectorExtension.GenerationTarget.Common\n    //multiplatformGenerationTarget = ComposeVectorExtension.GenerationTarget.Android\n\n    // Generate androidx.compose.ui.tooling.preview.Preview functions for Android target or not\n    //\n    // Optional\n    // Default: true\n    generateAndroidPreview = true\n\n    // Generate org.jetbrains.compose.ui.tooling.preview.Preview functions for KMP common target or not\n    //\n    // Optional\n    // Default: false\n    generateJetbrainsPreview = false\n\n    // Generate androidx.compose.desktop.ui.tooling.preview.Preview functions for KMP common target or not\n    //\n    // Optional\n    // Default: true\n    generateDesktopPreview = true\n}\n```\n\n## Debug with logging\n\nThis plugin will be logging with `--info` gradle option.\n\n```shell\n% ./gradlew :app:generateImageVector --info\n...\n\u003e Task :app:generateImageVector\nBuild cache key for task ':app:generateImageVector' is dc07551486b4a33c25fa9d1ef7b64905\nTask ':app:generateImageVector' is not up-to-date because:\n  Task.upToDateWhen is false.\nThe input changes require a full rebuild for incremental task ':app:generateImageVector'.\nclean .../app/build/compose-vector/src/main/kotlin because of initial build or full rebuild for incremental task and there in under project build directory.\nchanged: Input file .../app/images/icons/automirrored/filled/undo.svg added for rebuild.\nconvert icons/automirrored/filled/undo.svg to icons/automirrored/filled/Undo.kt\nchanged: Input file .../app/images/icons/filled/undo.svg added for rebuild.\nconvert icons/filled/undo.svg to icons/filled/Undo.kt\nwrite object file: Icons.kt\nStored cache entry for task ':app:generateImageVector' with cache key dc07551486b4a33c25fa9d1ef7b64905\n...\n```\n\n## Use SVG to ImageVector converter as Java Library\n\nSVG to ImageVector converter logic is packaged as Java library, so it can be used from your java CLI or applications.\n\n`build.gradle.kts`\n\n```kotlin\nplugins {\n    id(\"org.jetbrains.kotlin.jvm\")\n}\n...\ndependencies {\n    implementation(\"io.github.irgaly.compose.vector:compose-vector:1.1.0\")\n}\n```\n\nThen use `SvgParser` class and `ImageVectorGenerator` class.\n\n```kotlin\nval inputStream = ... // SVG content as InputStream from File or String etc...\nval imageVector: io.github.irgaly.compose.vector.node.ImageVector = SvgParser(object : Logger {\n    override fun debug(message: String) {\n        println(\"debug: $message\")\n    }\n\n    override fun info(message: String) {\n        println(\"info: $message\")\n    }\n\n    override fun warn(message: String, error: Exception?) {\n        println(\"warn: $message | $error\")\n    }\n\n    override fun error(message: String, error: Exception?) {\n        println(\"error: $message | $error\")\n    }\n}).parse(\n    inputStream,\n    name = \"Icon\"\n)\nval kotlinSource: String = ImageVectorGenerator().generate(\n    imageVector = imageVector,\n    destinationPackage = \"io.github.irgaly.icons\",\n    receiverClasses = listOf(\"Icons\", \"AutoMirrored\", \"Filled\"),\n    extensionPackage = \"io.github.irgaly.icons.automirrored.filled\",\n    hasAndroidPreview = true,\n)\nprintln(kotlinSource)\n```\n\n## Supported SVG specifications\n\nThis plugin's converter is using [Apache Batik](https://xmlgraphics.apache.org/batik/) SVG parser,\nand supports basics specifications of SVG 1.2 + CSS style tag.\n\nHere is a supporting table.\n\n| SVG tag        | SVG attribute                                                                            | Supporting Status                                                 |\n|----------------|------------------------------------------------------------------------------------------|-------------------------------------------------------------------|\n| (any)          | id, class                                                                                | :white_check_mark:                                                |\n| (any)          | style                                                                                    | :white_check_mark:                                                |\n| (any)          | transform                                                                                | :white_check_mark:                                                |\n| (any)          | display                                                                                  | :white_check_mark:                                                |\n| (any)          | visibility                                                                               | :white_check_mark:                                                |\n| (any)          | color                                                                                    | :white_check_mark:                                                |\n| (any)          | fill, fill-opacity, fill-rule                                                            | :white_check_mark:                                                |\n| (any)          | stroke, stroke-opacity, stroke-width, stroke-linecap, stroke-linejoin, stroke-miterlimit | :white_check_mark:                                                |\n| (any)          | clip-path, clip-rule, clipPathUnits                                                      | :white_check_mark:                                                |\n| svg            | viewBox, width, height                                                                   | :white_check_mark:\u003cbr/\u003eNested SVG tag is supported.               |\n| symbol         | viewBox, x, y, width, height                                                             | :white_check_mark:                                                |\n| g              |                                                                                          | :white_check_mark:                                                |\n| path           | d                                                                                        | :white_check_mark:                                                |\n| rect           | x, y, width, height, rx, ry                                                              | :white_check_mark:                                                |\n| circle         | cx, cy, r                                                                                | :white_check_mark:                                                |\n| ellipse        | cx, cy, rx, ry                                                                           | :white_check_mark:                                                |\n| line           | x1, x2, y1, y2                                                                           | :white_check_mark:                                                |\n| polyline       | points                                                                                   | :white_check_mark:                                                |\n| polygon        | points                                                                                   | :white_check_mark:                                                |\n| clipPath       |                                                                                          | :white_check_mark:                                                |\n| defs           |                                                                                          | :white_check_mark:                                                |\n| linearGradient | gradientUnits, spreadMethod, x1, x2, y1, y2                                              | :white_check_mark:                                                |\n| radialGradient | gradientUnits, cx, cy, fr                                                                | :white_check_mark:                                                |\n| stop           | offset, stop-color                                                                       | :white_check_mark:                                                |\n| use            | href, xlink:href                                                                         | :white_check_mark:                                                |\n| a              |                                                                                          | a tag is treated as same as g tag. No clickable feature.          |\n| title          |                                                                                          | This tag is just ignored                                          |\n| desc           |                                                                                          | This tag is just ignored                                          |\n| metadata       |                                                                                          | This tag is just ignored                                          |\n| view           |                                                                                          | This tag is just ignored                                          |\n| script         |                                                                                          | This tag is just ignored                                          |\n| cursor         |                                                                                          | This tag is just ignored                                          |\n| animate        |                                                                                          | Not supported because ImageVector doesn't have animation feature. |\n| text           |                                                                                          | Not supported because ImageVector can't draw texts.               |\n| image          |                                                                                          | Not supported because ImageVector can't draw images.              |\n| filter         |                                                                                          | Not supported.                                                    |\n| mask           |                                                                                          | Not supported.                                                    |\n| switch         |                                                                                          | Not supported.                                                    |\n| foreignObject  |                                                                                          | Not supported.                                                    |\n\n### Color format style\n\nCSS4 Named Colors and sRGB colors are supported for color format.\n\n| Color Format Style                                                          | Supporting Status  |\n|-----------------------------------------------------------------------------|--------------------|\n| [CSS4 Named Colors](https://www.w3.org/TR/css-color-4/#named-colors)        | :white_check_mark: |\n| rgb(0 0 0), rgb(0% 0% 0%), rgb(0, 0, 0)                                     | :white_check_mark: |\n| rgb(0 0 0 0), rgb(0 0 0 / 0), rgb(0% 0% 0% 0%), rgb(0, 0, 0, 0)             | :white_check_mark: |\n| rgba(0 0 0 0), rgba(0 0 0 / 0), rgba(0%, 0%, 0%, 0%)                        | :white_check_mark: |\n| #RRGGBB, #RGB                                                               | :white_check_mark: |\n| #RRGGBBAA, #RGBA                                                            | :white_check_mark: |\n\n\n\n\n\n\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Firgaly%2Fcompose-vector-plugin","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Firgaly%2Fcompose-vector-plugin","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Firgaly%2Fcompose-vector-plugin/lists"}