SVG2DrawIOLib 1.2.2__tar.gz → 1.3.4__tar.gz
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.
- {svg2drawiolib-1.2.2 → svg2drawiolib-1.3.4}/.gitignore +5 -4
- {svg2drawiolib-1.2.2 → svg2drawiolib-1.3.4}/CHANGELOG.md +82 -0
- {svg2drawiolib-1.2.2 → svg2drawiolib-1.3.4}/PKG-INFO +55 -1
- {svg2drawiolib-1.2.2 → svg2drawiolib-1.3.4}/QUICKSTART.md +53 -0
- {svg2drawiolib-1.2.2 → svg2drawiolib-1.3.4}/README.md +49 -0
- {svg2drawiolib-1.2.2 → svg2drawiolib-1.3.4}/pyproject.toml +45 -0
- {svg2drawiolib-1.2.2 → svg2drawiolib-1.3.4}/src/SVG2DrawIOLib/__about__.py +1 -1
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/api/__init__.py +1 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/api/dependencies.py +19 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/api/exceptions.py +27 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/api/main.py +95 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/api/models/__init__.py +1 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/api/models/responses.py +64 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/api/routers/__init__.py +1 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/api/routers/add.py +102 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/api/routers/create.py +84 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/api/routers/extract.py +71 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/api/routers/inspect.py +71 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/api/routers/list.py +38 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/api/routers/remove.py +55 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/api/routers/rename.py +74 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/api/routers/split_paths.py +62 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/api/routers/validate.py +60 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/api/services/__init__.py +1 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/api/services/processing.py +281 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/cli/web.py +111 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/404/index.html +1 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/404.html +1 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/__next.__PAGE__.txt +9 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/__next._full.txt +20 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/__next._head.txt +5 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/__next._index.txt +8 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/__next._tree.txt +2 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/_next/static/chunks/05be8470af537e1f.js +1 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/_next/static/chunks/1627bf2f54f2038d.js +4 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/_next/static/chunks/25d8eaefeee06316.js +5 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/_next/static/chunks/31674d9a34dac40b.js +2 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/_next/static/chunks/3650d5168a6ef170.js +5 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/_next/static/chunks/39c7ed480da232e5.js +5 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/_next/static/chunks/43e71249fcda7b06.css +1 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/_next/static/chunks/8d392274dc4eebdc.js +5 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/_next/static/chunks/92ae03676f2ba60b.js +5 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/_next/static/chunks/98972599ae0898f2.js +1 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/_next/static/chunks/a6dad97d9634a72d.js +1 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/_next/static/chunks/a6dad97d9634a72d.js.map +1 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/_next/static/chunks/cabf41855a3523b5.js +5 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/_next/static/chunks/d2be314c3ece3fbe.js +1 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/_next/static/chunks/e3831ae40009cd4c.js +1 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/_next/static/chunks/f2f58a7e93290fbb.js +1 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/_next/static/chunks/ff1a16fafef87110.js +1 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/_next/static/chunks/turbopack-6ce0a7a6834ef0a1.js +4 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/_next/static/u3W_d4CFznT12yceuuF-1/_buildManifest.js +11 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/_next/static/u3W_d4CFznT12yceuuF-1/_clientMiddlewareManifest.json +1 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/_next/static/u3W_d4CFznT12yceuuF-1/_ssgManifest.js +1 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/_not-found/__next._full.txt +16 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/_not-found/__next._head.txt +5 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/_not-found/__next._index.txt +8 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/_not-found/__next._not-found.__PAGE__.txt +5 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/_not-found/__next._not-found.txt +4 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/_not-found/__next._tree.txt +2 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/_not-found/index.html +1 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/_not-found/index.txt +16 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/create/__next._full.txt +17 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/create/__next._head.txt +5 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/create/__next._index.txt +8 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/create/__next._tree.txt +2 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/create/__next.create.__PAGE__.txt +6 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/create/__next.create.txt +4 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/create/index.html +1 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/create/index.txt +17 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/extract/__next._full.txt +17 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/extract/__next._head.txt +5 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/extract/__next._index.txt +8 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/extract/__next._tree.txt +2 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/extract/__next.extract.__PAGE__.txt +6 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/extract/__next.extract.txt +4 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/extract/index.html +1 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/extract/index.txt +17 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/index.html +1 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/index.txt +20 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/inspect/__next._full.txt +17 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/inspect/__next._head.txt +5 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/inspect/__next._index.txt +8 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/inspect/__next._tree.txt +2 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/inspect/__next.inspect.__PAGE__.txt +6 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/inspect/__next.inspect.txt +4 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/inspect/index.html +1 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/inspect/index.txt +17 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/manage/__next._full.txt +17 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/manage/__next._head.txt +5 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/manage/__next._index.txt +8 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/manage/__next._tree.txt +2 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/manage/__next.manage.__PAGE__.txt +6 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/manage/__next.manage.txt +4 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/manage/index.html +1 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/manage/index.txt +17 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/split-paths/__next._full.txt +17 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/split-paths/__next._head.txt +5 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/split-paths/__next._index.txt +8 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/split-paths/__next._tree.txt +2 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/split-paths/__next.split-paths.__PAGE__.txt +6 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/split-paths/__next.split-paths.txt +4 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/split-paths/index.html +1 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/split-paths/index.txt +17 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/validate/__next._full.txt +17 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/validate/__next._head.txt +5 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/validate/__next._index.txt +8 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/validate/__next._tree.txt +2 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/validate/__next.validate.__PAGE__.txt +6 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/validate/__next.validate.txt +4 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/validate/index.html +1 -0
- svg2drawiolib-1.3.4/src/SVG2DrawIOLib/web/validate/index.txt +17 -0
- svg2drawiolib-1.3.4/tests/test_api_processing.py +339 -0
- svg2drawiolib-1.3.4/tests/test_api_routers.py +613 -0
- svg2drawiolib-1.3.4/tests/test_cli_web.py +297 -0
- svg2drawiolib-1.2.2/.github/workflows/ci.yml +0 -82
- svg2drawiolib-1.2.2/.github/workflows/publish.yml +0 -95
- svg2drawiolib-1.2.2/.github/workflows/release.yml +0 -86
- svg2drawiolib-1.2.2/.pre-commit-config.yaml +0 -36
- svg2drawiolib-1.2.2/ARCHITECTURE.md +0 -833
- svg2drawiolib-1.2.2/MANIFEST.in +0 -19
- svg2drawiolib-1.2.2/Makefile +0 -66
- svg2drawiolib-1.2.2/uv.lock +0 -900
- {svg2drawiolib-1.2.2 → svg2drawiolib-1.3.4}/CONTRIBUTING.md +0 -0
- {svg2drawiolib-1.2.2 → svg2drawiolib-1.3.4}/LICENSE.txt +0 -0
- {svg2drawiolib-1.2.2 → svg2drawiolib-1.3.4}/src/SVG2DrawIOLib/__init__.py +0 -0
- {svg2drawiolib-1.2.2 → svg2drawiolib-1.3.4}/src/SVG2DrawIOLib/cli/__init__.py +0 -0
- {svg2drawiolib-1.2.2 → svg2drawiolib-1.3.4}/src/SVG2DrawIOLib/cli/add.py +0 -0
- {svg2drawiolib-1.2.2 → svg2drawiolib-1.3.4}/src/SVG2DrawIOLib/cli/create.py +0 -0
- {svg2drawiolib-1.2.2 → svg2drawiolib-1.3.4}/src/SVG2DrawIOLib/cli/create_helpers.py +0 -0
- {svg2drawiolib-1.2.2 → svg2drawiolib-1.3.4}/src/SVG2DrawIOLib/cli/extract.py +0 -0
- {svg2drawiolib-1.2.2 → svg2drawiolib-1.3.4}/src/SVG2DrawIOLib/cli/helpers.py +0 -0
- {svg2drawiolib-1.2.2 → svg2drawiolib-1.3.4}/src/SVG2DrawIOLib/cli/inspect.py +0 -0
- {svg2drawiolib-1.2.2 → svg2drawiolib-1.3.4}/src/SVG2DrawIOLib/cli/list.py +0 -0
- {svg2drawiolib-1.2.2 → svg2drawiolib-1.3.4}/src/SVG2DrawIOLib/cli/remove.py +0 -0
- {svg2drawiolib-1.2.2 → svg2drawiolib-1.3.4}/src/SVG2DrawIOLib/cli/rename.py +0 -0
- {svg2drawiolib-1.2.2 → svg2drawiolib-1.3.4}/src/SVG2DrawIOLib/cli/split_paths.py +0 -0
- {svg2drawiolib-1.2.2 → svg2drawiolib-1.3.4}/src/SVG2DrawIOLib/cli/validate.py +0 -0
- {svg2drawiolib-1.2.2 → svg2drawiolib-1.3.4}/src/SVG2DrawIOLib/icon_analyzer.py +0 -0
- {svg2drawiolib-1.2.2 → svg2drawiolib-1.3.4}/src/SVG2DrawIOLib/library_manager.py +0 -0
- {svg2drawiolib-1.2.2 → svg2drawiolib-1.3.4}/src/SVG2DrawIOLib/models.py +0 -0
- {svg2drawiolib-1.2.2 → svg2drawiolib-1.3.4}/src/SVG2DrawIOLib/path_splitter.py +0 -0
- {svg2drawiolib-1.2.2 → svg2drawiolib-1.3.4}/src/SVG2DrawIOLib/svg_processor.py +0 -0
- {svg2drawiolib-1.2.2 → svg2drawiolib-1.3.4}/src/SVG2DrawIOLib/validator.py +0 -0
- {svg2drawiolib-1.2.2 → svg2drawiolib-1.3.4}/src/SVG2DrawIOLib/xml_utils.py +0 -0
- {svg2drawiolib-1.2.2 → svg2drawiolib-1.3.4}/tests/__init__.py +0 -0
- {svg2drawiolib-1.2.2 → svg2drawiolib-1.3.4}/tests/conftest.py +0 -0
- {svg2drawiolib-1.2.2 → svg2drawiolib-1.3.4}/tests/test_cli.py +0 -0
- {svg2drawiolib-1.2.2 → svg2drawiolib-1.3.4}/tests/test_cli_create_helpers.py +0 -0
- {svg2drawiolib-1.2.2 → svg2drawiolib-1.3.4}/tests/test_cli_create_split.py +0 -0
- {svg2drawiolib-1.2.2 → svg2drawiolib-1.3.4}/tests/test_cli_extract.py +0 -0
- {svg2drawiolib-1.2.2 → svg2drawiolib-1.3.4}/tests/test_cli_helpers.py +0 -0
- {svg2drawiolib-1.2.2 → svg2drawiolib-1.3.4}/tests/test_cli_inspect.py +0 -0
- {svg2drawiolib-1.2.2 → svg2drawiolib-1.3.4}/tests/test_cli_rename.py +0 -0
- {svg2drawiolib-1.2.2 → svg2drawiolib-1.3.4}/tests/test_cli_validate.py +0 -0
- {svg2drawiolib-1.2.2 → svg2drawiolib-1.3.4}/tests/test_css_modes.py +0 -0
- {svg2drawiolib-1.2.2 → svg2drawiolib-1.3.4}/tests/test_library_manager.py +0 -0
- {svg2drawiolib-1.2.2 → svg2drawiolib-1.3.4}/tests/test_models.py +0 -0
- {svg2drawiolib-1.2.2 → svg2drawiolib-1.3.4}/tests/test_path_splitter.py +0 -0
- {svg2drawiolib-1.2.2 → svg2drawiolib-1.3.4}/tests/test_svg_processor.py +0 -0
- {svg2drawiolib-1.2.2 → svg2drawiolib-1.3.4}/tests/test_svg_processor_coverage.py +0 -0
- {svg2drawiolib-1.2.2 → svg2drawiolib-1.3.4}/tests/test_viewbox_improvements.py +0 -0
- {svg2drawiolib-1.2.2 → svg2drawiolib-1.3.4}/tests/test_xml_utils.py +0 -0
|
@@ -39,13 +39,14 @@ debug/
|
|
|
39
39
|
/test_*.xml
|
|
40
40
|
/test_*.py
|
|
41
41
|
|
|
42
|
+
# Bundled web UI (built artifact — not source)
|
|
43
|
+
src/SVG2DrawIOLib/web/*
|
|
44
|
+
!src/SVG2DrawIOLib/web/.gitkeep
|
|
45
|
+
|
|
42
46
|
# web-ui (Next.js)
|
|
43
47
|
web-ui/node_modules/
|
|
44
48
|
web-ui/.next/
|
|
45
49
|
web-ui/out/
|
|
46
50
|
web-ui/.env.local
|
|
47
51
|
web-ui/.env*.local
|
|
48
|
-
|
|
49
|
-
# api (FastAPI)
|
|
50
|
-
api/__pycache__/
|
|
51
|
-
api/**/__pycache__/
|
|
52
|
+
!web-ui/.env.production
|
|
@@ -5,6 +5,82 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [1.3.4] - 2026-02-22
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- **PyPI wheel packaging**: Fixed project build file to remove web includes/excludes that were breaking CI/CD
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
|
|
16
|
+
- **`Makefile`**: Simplified `build-release` target to remove `.gitkeep` preservation logic since the placeholder is not needed in distribution builds.
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
## [1.3.3] - 2026-02-22
|
|
20
|
+
|
|
21
|
+
### Fixed
|
|
22
|
+
|
|
23
|
+
- **PyPI wheel packaging**: Fixed duplicate `.gitkeep` file in wheel that caused PyPI upload rejection. Modified `build-release` Makefile target to not preserve the `.gitkeep` placeholder file when copying web UI build artifacts, as it's only needed for development and editable installs.
|
|
24
|
+
|
|
25
|
+
### Changed
|
|
26
|
+
|
|
27
|
+
- **`Makefile`**: Simplified `build-release` target to remove `.gitkeep` preservation logic since the placeholder is not needed in distribution builds.
|
|
28
|
+
|
|
29
|
+
## [1.3.2] - 2026-02-22
|
|
30
|
+
|
|
31
|
+
### Fixed
|
|
32
|
+
|
|
33
|
+
- **Editable install compatibility**: Added `.gitkeep` placeholder file in `src/SVG2DrawIOLib/web/` directory to enable editable installs (`pip install -e .`) to work before the web UI is built. This fixes CI/CD workflows that install in editable mode for testing before building the web UI.
|
|
34
|
+
- **Web UI packaging**: Fixed `pyproject.toml` hatchling configuration to properly include the web UI static files in the built wheel and sdist. Changed from `artifacts` to `force-include` configuration for both wheel and sdist targets. The web UI directory (`src/SVG2DrawIOLib/web/`) is now correctly included in PyPI releases, ensuring `pip install SVG2DrawIOLib[web]` followed by `svg2drawiolib web` works out of the box.
|
|
35
|
+
|
|
36
|
+
### Changed
|
|
37
|
+
|
|
38
|
+
- **`.gitignore`**: Updated web directory exclusion pattern to allow `.gitkeep` placeholder file while still ignoring all build artifacts.
|
|
39
|
+
- **`Makefile`**: Updated `build-release` target to preserve `.gitkeep` file when copying web UI build artifacts.
|
|
40
|
+
|
|
41
|
+
## [1.3.1] - 2026-02-22
|
|
42
|
+
|
|
43
|
+
### Fixed
|
|
44
|
+
|
|
45
|
+
- **Security: Data URI sanitization** (Bug #27): Updated SVG sanitization to only block dangerous data: URIs (`data:text/html`, `data:text/javascript`, `data:application/javascript`, `data:application/x-javascript`) while allowing safe image data: URIs (`data:image/png`, `data:image/jpeg`, `data:image/svg+xml`, etc.) for legitimate embedded images.
|
|
46
|
+
- **Security: Case-insensitive element filtering** (Bug #28): Made dangerous element checking case-insensitive to prevent sanitization bypass via case variants like `<Script>`, `<SCRIPT>`, or `<ForeignObject>`. Updated `_DANGEROUS_ELEMENTS` set to store lowercase values and added `.lower()` call during comparison.
|
|
47
|
+
- **API: Duplicate error handling** (Bug #29): Extracted duplicate library error handling logic into shared `handle_library_value_error()` helper function in `processing.py`. Updated five routers (`add`, `remove`, `list`, `extract`, `inspect`) to use the centralized helper, eliminating code duplication.
|
|
48
|
+
- **API: Type safety** (Bug #31): Changed `handle_library_value_error()` return type from `-> None` to `-> NoReturn` to accurately reflect that the function always raises an exception and never returns, improving type checker guarantees.
|
|
49
|
+
- **API: Rename endpoint error handling** (Bug #32): Added "Invalid library" error check to rename endpoint to return 422 for malformed library files instead of 500 internal server error, consistent with other endpoints.
|
|
50
|
+
- **API: Icon names validation** (Bug #26): Added element type validation to `parse_icon_names()` to ensure all list elements are strings, preventing unhashable type errors downstream when non-string values are passed.
|
|
51
|
+
- **Next.js dev mode warning** (Bug #30): Made `output: "export"` conditional in `next.config.ts` (only set in production) to eliminate Next.js warning about rewrites not working with static exports during development.
|
|
52
|
+
|
|
53
|
+
### Changed
|
|
54
|
+
|
|
55
|
+
- **Web UI default**: Changed "Inject CSS classes" checkbox default from `false` to `true` in both CreateTab and ManageTab components for better out-of-box experience.
|
|
56
|
+
|
|
57
|
+
## [1.3.0] - 2026-02-21
|
|
58
|
+
|
|
59
|
+
### Added
|
|
60
|
+
|
|
61
|
+
- **Browser-based Web UI**: New optional web interface that exposes all CLI commands as a browser UI. Install with `pip install "SVG2DrawIOLib[web]"` and launch with `svg2drawio web`. The server automatically opens the browser and serves both the API and frontend from a single process on port 8000.
|
|
62
|
+
- **Six tabs**: Create (convert SVGs to a new library), Manage (add icons, remove icons, rename icons), Extract (save icons as SVG files), Inspect (view icon details and SVG previews), Validate (structural integrity report), Split Paths (split compound paths for per-path color control)
|
|
63
|
+
- **FastAPI sidecar** (`src/SVG2DrawIOLib/api/`): Nine REST endpoints under `/api/*` wrapping the same Python services used by the CLI. Reuses `process_svg_files()`, `determine_sizing_strategy()`, `sanitize_filename()`, and `safe_path_join()` directly — no logic duplication.
|
|
64
|
+
- **SVG sanitization**: Uploaded SVG files are stripped of `<script>`, `<foreignObject>`, `javascript:` hrefs, and event-handler attributes before processing. Enforces a 10 MB per-file size limit.
|
|
65
|
+
- **Bundled static export**: The pre-built Next.js UI is copied into `src/SVG2DrawIOLib/web/` at release time and included in the Python wheel via hatchling artifacts — no Node.js required at runtime.
|
|
66
|
+
- **`[web]` optional dependency group**: `fastapi>=0.115.0`, `uvicorn[standard]>=0.32.0`, `python-multipart>=0.0.12`.
|
|
67
|
+
- **`svg2drawio` entry point**: Added as a shorter alias alongside `SVG2DrawIOLib` and `svg2drawiolib`.
|
|
68
|
+
- **Web UI Makefile targets**: `make dev-api` (FastAPI with hot-reload), `make dev-web` (Next.js dev server), `make dev-all` (both together), `make build-web` (Next.js static export), `make build-release` (build + copy into package), `make start-web` (build then launch).
|
|
69
|
+
|
|
70
|
+
### Fixed
|
|
71
|
+
|
|
72
|
+
- **Windows `FileResponse` race condition** (`api/routers/`): All file-returning endpoints (`create`, `add`, `remove`, `rename`, `split-paths`) now use `Response(content=path.read_bytes())` instead of `FileResponse(path)`. `FileResponse` streams lazily — on Windows the `get_temp_dir()` dependency's `finally` cleanup block could delete the temp directory before the file body was streamed, causing "Failed to fetch" in the browser with no server-side error logged.
|
|
73
|
+
- **Static build CORS mismatch** (`web-ui/src/lib/api.ts`): Changed the `API_BASE` fallback from `"http://localhost:8000"` to `""` so the static export uses relative URLs (`/api/create` instead of `http://localhost:8000/api/create`). This fixes "Failed to fetch" when the browser opens to `http://127.0.0.1:8000` (the CLI's default bind address) while the hardcoded URL pointed to `http://localhost:8000` — a cross-origin mismatch the CORS policy rejected.
|
|
74
|
+
- **Dev-mode API routing** (`web-ui/next.config.ts`): Added a conditional dev-mode proxy rewrite that forwards `/api/*` to the FastAPI server (`http://localhost:8000`) when running `next dev`, so `make dev-all` works without a `.env.local` file. The rewrite is omitted during `next build` (static export does not support rewrites).
|
|
75
|
+
- **Next.js RSC `__PAGE__.txt` 404s**: `make build-release` now renames RSC page payload files from their on-disk subdirectory form (`create/__next.create/__PAGE__.txt`) to the flat dot-separated form (`create/__next.create.__PAGE__.txt`) that the browser requests. Starlette's `StaticFiles` serves paths literally, so the mismatched filenames caused 404s that silently broke client-side navigation.
|
|
76
|
+
- **Cross-platform `build-release` target**: Replaced Unix-only `rm -rf` and `cp -r` shell commands in the Makefile with a Python one-liner using `shutil.rmtree` and `shutil.copytree`, which works on Windows without Git Bash or WSL.
|
|
77
|
+
|
|
78
|
+
### Changed
|
|
79
|
+
|
|
80
|
+
- **`pyproject.toml`**: Added `[web]` optional dependency group; added `svg2drawio` script entry point; added `[tool.hatch.build.targets.wheel] artifacts` to include the gitignored `src/SVG2DrawIOLib/web/` directory in the built wheel.
|
|
81
|
+
- **`.gitignore`**: Added `src/SVG2DrawIOLib/web/` (generated build artifact); removed stale `api/__pycache__/` entries from the old top-level `api/` directory.
|
|
82
|
+
- **Documentation**: Updated `README.md`, `QUICKSTART.md`, and `ARCHITECTURE.md` to document the web UI feature, installation, tab-to-command mapping, developer build workflow, FastAPI sidecar architecture, and bundled static export path resolution.
|
|
83
|
+
|
|
8
84
|
## [1.2.1] - 2026-02-09
|
|
9
85
|
|
|
10
86
|
### Changed
|
|
@@ -203,5 +279,11 @@ The project follows SOLID principles with clear module boundaries:
|
|
|
203
279
|
- `library_manager.py`: Library file management
|
|
204
280
|
- `cli/`: Modular CLI with dynamic command loading
|
|
205
281
|
|
|
282
|
+
[1.3.0]: https://github.com/jamesbconner/SVG2DrawIOLib/compare/v1.2.1...v1.3.0
|
|
283
|
+
[1.2.1]: https://github.com/jamesbconner/SVG2DrawIOLib/compare/v1.2.0...v1.2.1
|
|
284
|
+
[1.2.0]: https://github.com/jamesbconner/SVG2DrawIOLib/compare/v1.1.2...v1.2.0
|
|
285
|
+
[1.1.2]: https://github.com/jamesbconner/SVG2DrawIOLib/compare/v1.1.1...v1.1.2
|
|
286
|
+
[1.1.1]: https://github.com/jamesbconner/SVG2DrawIOLib/compare/v1.1.0...v1.1.1
|
|
287
|
+
[1.1.0]: https://github.com/jamesbconner/SVG2DrawIOLib/compare/v1.0.1...v1.1.0
|
|
206
288
|
[1.0.1]: https://github.com/jamesbconner/SVG2DrawIOLib/compare/v1.0.0...v1.0.1
|
|
207
289
|
[1.0.0]: https://github.com/jamesbconner/SVG2DrawIOLib/releases/tag/v1.0.0
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: SVG2DrawIOLib
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.3.4
|
|
4
4
|
Summary: Generate DrawIO shape libraries from SVGs
|
|
5
5
|
Project-URL: Homepage, https://github.com/jamesbconner/SVG2DrawIOLib
|
|
6
6
|
Project-URL: Documentation, https://github.com/jamesbconner/SVG2DrawIOLib#readme
|
|
@@ -23,6 +23,7 @@ Requires-Dist: rich>=13.0.0
|
|
|
23
23
|
Requires-Dist: svgelements>=1.9.0
|
|
24
24
|
Provides-Extra: dev
|
|
25
25
|
Requires-Dist: bandit>=1.7.0; extra == 'dev'
|
|
26
|
+
Requires-Dist: httpx>=0.27.0; extra == 'dev'
|
|
26
27
|
Requires-Dist: mypy>=1.18.0; extra == 'dev'
|
|
27
28
|
Requires-Dist: pip>=26.0.1; extra == 'dev'
|
|
28
29
|
Requires-Dist: pre-commit>=4.4.0; extra == 'dev'
|
|
@@ -31,6 +32,10 @@ Requires-Dist: pytest>=8.4.2; extra == 'dev'
|
|
|
31
32
|
Requires-Dist: ruff>=0.14.4; extra == 'dev'
|
|
32
33
|
Requires-Dist: twine>=5.0.0; extra == 'dev'
|
|
33
34
|
Requires-Dist: uv>=0.10.0; extra == 'dev'
|
|
35
|
+
Provides-Extra: web
|
|
36
|
+
Requires-Dist: fastapi>=0.115.0; extra == 'web'
|
|
37
|
+
Requires-Dist: python-multipart>=0.0.12; extra == 'web'
|
|
38
|
+
Requires-Dist: uvicorn[standard]>=0.32.0; extra == 'web'
|
|
34
39
|
Description-Content-Type: text/markdown
|
|
35
40
|
|
|
36
41
|
# SVG2DrawIOLib
|
|
@@ -55,6 +60,7 @@ Convert SVG files into DrawIO/diagrams.net shape libraries with support for colo
|
|
|
55
60
|
- 🎨 **Color Customization**: Inject CSS classes to enable color editing directly in DrawIO's interface
|
|
56
61
|
- 📏 **Flexible Sizing**: Proportional scaling with aspect ratio preservation, or fixed dimensions
|
|
57
62
|
- 📚 **Library Management**: Create new libraries, add/remove icons, and list contents
|
|
63
|
+
- 🌐 **Browser-based Web UI**: All commands available in a local web interface — no command line required
|
|
58
64
|
- 🚀 **Modern CLI**: Beautiful, colorful output with rich-click
|
|
59
65
|
- 🔧 **Modern Python Stack**: Built with ruff, mypy, bandit, pytest, and pre-commit hooks
|
|
60
66
|
|
|
@@ -93,6 +99,54 @@ SVG2DrawIOLib create icons/ --css -o colorable-icons.xml
|
|
|
93
99
|
SVG2DrawIOLib create icons/ --max-size 64 -o large-icons.xml -R
|
|
94
100
|
```
|
|
95
101
|
|
|
102
|
+
## Web UI
|
|
103
|
+
|
|
104
|
+
All CLI commands are available as a browser-based interface. Install with the `web` optional dependencies and launch with a single command:
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
pip install 'SVG2DrawIOLib[web]'
|
|
108
|
+
svg2drawio web
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
This starts a local FastAPI server and opens the UI automatically in your default browser at `http://127.0.0.1:8000`.
|
|
112
|
+
|
|
113
|
+
**Available tabs:**
|
|
114
|
+
|
|
115
|
+
| Tab | Equivalent CLI command |
|
|
116
|
+
|-----|------------------------|
|
|
117
|
+
| Create | `svg2drawio create` |
|
|
118
|
+
| Manage (Add / Remove / Rename) | `svg2drawio add` / `remove` / `rename` |
|
|
119
|
+
| Extract | `svg2drawio extract` |
|
|
120
|
+
| Inspect | `svg2drawio inspect` |
|
|
121
|
+
| Validate | `svg2drawio validate` |
|
|
122
|
+
| Split Paths | `svg2drawio split-paths` |
|
|
123
|
+
|
|
124
|
+
**Options:**
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
svg2drawio web --host 0.0.0.0 # Listen on all interfaces
|
|
128
|
+
svg2drawio web --port 9000 # Custom port
|
|
129
|
+
svg2drawio web --no-browser # Don't open browser automatically
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Building from Source
|
|
133
|
+
|
|
134
|
+
If you are working from a source checkout, build the Next.js frontend first, then launch:
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
make build-release # builds web-ui/ and copies output into the Python package
|
|
138
|
+
svg2drawio web
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Or run the frontend and API separately during development:
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
make dev-api # FastAPI on :8000 (terminal 1)
|
|
145
|
+
make dev-web # Next.js on :3000 (terminal 2)
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
96
150
|
## Documentation
|
|
97
151
|
|
|
98
152
|
- [Quick Start Guide](QUICKSTART.md) - Get started quickly for users and developers
|
|
@@ -231,6 +231,41 @@ Options:
|
|
|
231
231
|
-q, --quiet Suppress output except errors
|
|
232
232
|
```
|
|
233
233
|
|
|
234
|
+
## Web UI
|
|
235
|
+
|
|
236
|
+
### Installation
|
|
237
|
+
```bash
|
|
238
|
+
pip install "SVG2DrawIOLib[web]"
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### Launch
|
|
242
|
+
```bash
|
|
243
|
+
svg2drawio web
|
|
244
|
+
# Opens http://127.0.0.1:8000 in your browser automatically
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
### Options
|
|
248
|
+
```bash
|
|
249
|
+
svg2drawio web --port 9000 # Use a different port
|
|
250
|
+
svg2drawio web --host 0.0.0.0 # Listen on all interfaces
|
|
251
|
+
svg2drawio web --no-browser # Don't auto-open the browser
|
|
252
|
+
svg2drawio web --ui-dir /path/to/ui # Use a custom pre-built UI directory
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
### Tabs
|
|
256
|
+
| Tab | Equivalent CLI Command |
|
|
257
|
+
|-----|----------------------|
|
|
258
|
+
| Create | `svg2drawio create` |
|
|
259
|
+
| Manage → Add Icons | `svg2drawio add` |
|
|
260
|
+
| Manage → Remove Icons | `svg2drawio remove` |
|
|
261
|
+
| Manage → Rename Icon | `svg2drawio rename` |
|
|
262
|
+
| Extract | `svg2drawio extract` |
|
|
263
|
+
| Inspect | `svg2drawio inspect` |
|
|
264
|
+
| Validate | `svg2drawio validate` |
|
|
265
|
+
| Split Paths | `svg2drawio split-paths` |
|
|
266
|
+
|
|
267
|
+
---
|
|
268
|
+
|
|
234
269
|
## For Developers
|
|
235
270
|
|
|
236
271
|
### Setup
|
|
@@ -267,6 +302,24 @@ make all # Run all checks
|
|
|
267
302
|
make clean # Clean build artifacts
|
|
268
303
|
```
|
|
269
304
|
|
|
305
|
+
### Web UI Development
|
|
306
|
+
```bash
|
|
307
|
+
# Install web dependencies and start FastAPI + Next.js dev servers
|
|
308
|
+
make dev-api # FastAPI only on port 8000 (with --reload)
|
|
309
|
+
make dev-web # Next.js dev server only (port 3000)
|
|
310
|
+
|
|
311
|
+
# Build the static export and copy into the Python package
|
|
312
|
+
make build-release # Runs npm build + copies output to src/SVG2DrawIOLib/web/
|
|
313
|
+
|
|
314
|
+
# Build and launch the web UI from the source tree
|
|
315
|
+
make start-web
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
The `web-ui/` directory contains the Next.js frontend source. The built static export
|
|
319
|
+
is copied to `src/SVG2DrawIOLib/web/` (gitignored — generated artifact) for bundling
|
|
320
|
+
into the Python wheel via `make build-release`. The FastAPI server at
|
|
321
|
+
`SVG2DrawIOLib.api.main:app` serves both the API (`/api/*`) and the static UI (`/`).
|
|
322
|
+
|
|
270
323
|
### Running Tests
|
|
271
324
|
```bash
|
|
272
325
|
# All tests
|
|
@@ -20,6 +20,7 @@ Convert SVG files into DrawIO/diagrams.net shape libraries with support for colo
|
|
|
20
20
|
- 🎨 **Color Customization**: Inject CSS classes to enable color editing directly in DrawIO's interface
|
|
21
21
|
- 📏 **Flexible Sizing**: Proportional scaling with aspect ratio preservation, or fixed dimensions
|
|
22
22
|
- 📚 **Library Management**: Create new libraries, add/remove icons, and list contents
|
|
23
|
+
- 🌐 **Browser-based Web UI**: All commands available in a local web interface — no command line required
|
|
23
24
|
- 🚀 **Modern CLI**: Beautiful, colorful output with rich-click
|
|
24
25
|
- 🔧 **Modern Python Stack**: Built with ruff, mypy, bandit, pytest, and pre-commit hooks
|
|
25
26
|
|
|
@@ -58,6 +59,54 @@ SVG2DrawIOLib create icons/ --css -o colorable-icons.xml
|
|
|
58
59
|
SVG2DrawIOLib create icons/ --max-size 64 -o large-icons.xml -R
|
|
59
60
|
```
|
|
60
61
|
|
|
62
|
+
## Web UI
|
|
63
|
+
|
|
64
|
+
All CLI commands are available as a browser-based interface. Install with the `web` optional dependencies and launch with a single command:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
pip install 'SVG2DrawIOLib[web]'
|
|
68
|
+
svg2drawio web
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
This starts a local FastAPI server and opens the UI automatically in your default browser at `http://127.0.0.1:8000`.
|
|
72
|
+
|
|
73
|
+
**Available tabs:**
|
|
74
|
+
|
|
75
|
+
| Tab | Equivalent CLI command |
|
|
76
|
+
|-----|------------------------|
|
|
77
|
+
| Create | `svg2drawio create` |
|
|
78
|
+
| Manage (Add / Remove / Rename) | `svg2drawio add` / `remove` / `rename` |
|
|
79
|
+
| Extract | `svg2drawio extract` |
|
|
80
|
+
| Inspect | `svg2drawio inspect` |
|
|
81
|
+
| Validate | `svg2drawio validate` |
|
|
82
|
+
| Split Paths | `svg2drawio split-paths` |
|
|
83
|
+
|
|
84
|
+
**Options:**
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
svg2drawio web --host 0.0.0.0 # Listen on all interfaces
|
|
88
|
+
svg2drawio web --port 9000 # Custom port
|
|
89
|
+
svg2drawio web --no-browser # Don't open browser automatically
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Building from Source
|
|
93
|
+
|
|
94
|
+
If you are working from a source checkout, build the Next.js frontend first, then launch:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
make build-release # builds web-ui/ and copies output into the Python package
|
|
98
|
+
svg2drawio web
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Or run the frontend and API separately during development:
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
make dev-api # FastAPI on :8000 (terminal 1)
|
|
105
|
+
make dev-web # Next.js on :3000 (terminal 2)
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
61
110
|
## Documentation
|
|
62
111
|
|
|
63
112
|
- [Quick Start Guide](QUICKSTART.md) - Get started quickly for users and developers
|
|
@@ -38,6 +38,11 @@ dependencies = [
|
|
|
38
38
|
dynamic = ["version"]
|
|
39
39
|
|
|
40
40
|
[project.optional-dependencies]
|
|
41
|
+
web = [
|
|
42
|
+
"fastapi>=0.115.0",
|
|
43
|
+
"uvicorn[standard]>=0.32.0",
|
|
44
|
+
"python-multipart>=0.0.12",
|
|
45
|
+
]
|
|
41
46
|
dev = [
|
|
42
47
|
"pytest>=8.4.2",
|
|
43
48
|
"pytest-cov>=6.0.0",
|
|
@@ -48,6 +53,7 @@ dev = [
|
|
|
48
53
|
"twine>=5.0.0",
|
|
49
54
|
"pip>=26.0.1",
|
|
50
55
|
"uv>=0.10.0",
|
|
56
|
+
"httpx>=0.27.0",
|
|
51
57
|
]
|
|
52
58
|
|
|
53
59
|
[project.urls]
|
|
@@ -60,10 +66,36 @@ Changelog = "https://github.com/jamesbconner/SVG2DrawIOLib/blob/main/CHANGELOG.m
|
|
|
60
66
|
[project.scripts]
|
|
61
67
|
SVG2DrawIOLib = "SVG2DrawIOLib.cli:cli"
|
|
62
68
|
svg2drawiolib = "SVG2DrawIOLib.cli:cli"
|
|
69
|
+
svg2drawio = "SVG2DrawIOLib.cli:cli"
|
|
63
70
|
|
|
64
71
|
[tool.hatch.version]
|
|
65
72
|
path = "src/SVG2DrawIOLib/__about__.py"
|
|
66
73
|
|
|
74
|
+
[tool.hatch.build.targets.wheel]
|
|
75
|
+
packages = ["src/SVG2DrawIOLib"]
|
|
76
|
+
|
|
77
|
+
[tool.hatch.build.targets.wheel.force-include]
|
|
78
|
+
"src/SVG2DrawIOLib/web" = "SVG2DrawIOLib/web"
|
|
79
|
+
|
|
80
|
+
[tool.hatch.build.targets.sdist]
|
|
81
|
+
include = [
|
|
82
|
+
"/src",
|
|
83
|
+
"/tests",
|
|
84
|
+
"/README.md",
|
|
85
|
+
"/LICENSE.txt",
|
|
86
|
+
"/CHANGELOG.md",
|
|
87
|
+
"/CONTRIBUTING.md",
|
|
88
|
+
"/QUICKSTART.md",
|
|
89
|
+
"/pyproject.toml",
|
|
90
|
+
]
|
|
91
|
+
|
|
92
|
+
[tool.hatch.build.targets.sdist.force-include]
|
|
93
|
+
"src/SVG2DrawIOLib/web" = "src/SVG2DrawIOLib/web"
|
|
94
|
+
|
|
95
|
+
# Editable installs work without the web directory
|
|
96
|
+
[tool.hatch.build.targets.editable]
|
|
97
|
+
packages = ["src/SVG2DrawIOLib"]
|
|
98
|
+
|
|
67
99
|
[tool.hatch.envs.default]
|
|
68
100
|
dependencies = [
|
|
69
101
|
"pytest>=8.0.0",
|
|
@@ -126,6 +158,7 @@ ignore = [
|
|
|
126
158
|
|
|
127
159
|
[tool.ruff.lint.per-file-ignores]
|
|
128
160
|
"tests/**/*.py" = ["ARG", "S101"]
|
|
161
|
+
"src/SVG2DrawIOLib/api/routers/*.py" = ["B008"] # Depends() in defaults is standard FastAPI pattern
|
|
129
162
|
|
|
130
163
|
[tool.mypy]
|
|
131
164
|
python_version = "3.13"
|
|
@@ -144,6 +177,18 @@ ignore_missing_imports = true
|
|
|
144
177
|
module = "rich_click.*"
|
|
145
178
|
ignore_missing_imports = true
|
|
146
179
|
|
|
180
|
+
[[tool.mypy.overrides]]
|
|
181
|
+
module = "pydantic.*"
|
|
182
|
+
ignore_missing_imports = true
|
|
183
|
+
|
|
184
|
+
[[tool.mypy.overrides]]
|
|
185
|
+
module = "fastapi.*"
|
|
186
|
+
ignore_missing_imports = true
|
|
187
|
+
|
|
147
188
|
[[tool.mypy.overrides]]
|
|
148
189
|
module = "SVG2DrawIOLib.cli.*"
|
|
149
190
|
disable_error_code = ["untyped-decorator"]
|
|
191
|
+
|
|
192
|
+
[[tool.mypy.overrides]]
|
|
193
|
+
module = "SVG2DrawIOLib.api.*"
|
|
194
|
+
disable_error_code = ["untyped-decorator"]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""SVG2DrawIOLib FastAPI sidecar."""
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"""FastAPI dependency providers."""
|
|
2
|
+
|
|
3
|
+
import shutil
|
|
4
|
+
import tempfile
|
|
5
|
+
from collections.abc import AsyncGenerator
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
async def get_temp_dir() -> AsyncGenerator[Path]:
|
|
10
|
+
"""Provide a temporary directory that is cleaned up after the request.
|
|
11
|
+
|
|
12
|
+
Yields:
|
|
13
|
+
Path to a temporary directory.
|
|
14
|
+
"""
|
|
15
|
+
tmp = tempfile.mkdtemp(prefix="svg2drawio_")
|
|
16
|
+
try:
|
|
17
|
+
yield Path(tmp)
|
|
18
|
+
finally:
|
|
19
|
+
shutil.rmtree(tmp, ignore_errors=True)
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"""Exception handlers for the FastAPI application."""
|
|
2
|
+
|
|
3
|
+
import xml.etree.ElementTree as ET
|
|
4
|
+
|
|
5
|
+
from fastapi import Request
|
|
6
|
+
from fastapi.responses import JSONResponse
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class ConflictError(Exception):
|
|
10
|
+
"""Exception raised when a resource conflict occurs (e.g., duplicate name)."""
|
|
11
|
+
|
|
12
|
+
pass
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
async def file_not_found_handler(_request: Request, exc: FileNotFoundError) -> JSONResponse:
|
|
16
|
+
"""Handle FileNotFoundError as HTTP 404."""
|
|
17
|
+
return JSONResponse(status_code=404, content={"detail": str(exc)})
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
async def conflict_error_handler(_request: Request, exc: ConflictError) -> JSONResponse:
|
|
21
|
+
"""Handle ConflictError as HTTP 409."""
|
|
22
|
+
return JSONResponse(status_code=409, content={"detail": str(exc)})
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
async def parse_error_handler(_request: Request, exc: ET.ParseError) -> JSONResponse:
|
|
26
|
+
"""Handle XML ParseError as HTTP 422."""
|
|
27
|
+
return JSONResponse(status_code=422, content={"detail": f"Invalid XML: {exc}"})
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"""FastAPI application for SVG2DrawIOLib web UI."""
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
import xml.etree.ElementTree as ET
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
from fastapi import FastAPI
|
|
8
|
+
from fastapi.middleware.cors import CORSMiddleware
|
|
9
|
+
from fastapi.staticfiles import StaticFiles
|
|
10
|
+
|
|
11
|
+
from SVG2DrawIOLib.__about__ import __version__
|
|
12
|
+
from SVG2DrawIOLib.api.exceptions import (
|
|
13
|
+
ConflictError,
|
|
14
|
+
conflict_error_handler,
|
|
15
|
+
file_not_found_handler,
|
|
16
|
+
parse_error_handler,
|
|
17
|
+
)
|
|
18
|
+
from SVG2DrawIOLib.api.models.responses import HealthResponse
|
|
19
|
+
from SVG2DrawIOLib.api.routers import (
|
|
20
|
+
add,
|
|
21
|
+
create,
|
|
22
|
+
extract,
|
|
23
|
+
inspect,
|
|
24
|
+
remove,
|
|
25
|
+
rename,
|
|
26
|
+
split_paths,
|
|
27
|
+
validate,
|
|
28
|
+
)
|
|
29
|
+
from SVG2DrawIOLib.api.routers import list as list_router
|
|
30
|
+
|
|
31
|
+
app = FastAPI(
|
|
32
|
+
title="SVG2DrawIOLib API",
|
|
33
|
+
description="Browser-based UI for converting SVG files into DrawIO shape libraries.",
|
|
34
|
+
version=__version__,
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
# CORS — allow origins from env var, defaulting to local Next.js dev server
|
|
38
|
+
allow_origins = os.getenv("CORS_ORIGINS", "http://localhost:3000").split(",")
|
|
39
|
+
|
|
40
|
+
app.add_middleware(
|
|
41
|
+
CORSMiddleware,
|
|
42
|
+
allow_origins=allow_origins,
|
|
43
|
+
allow_credentials=True,
|
|
44
|
+
allow_methods=["*"],
|
|
45
|
+
allow_headers=["*"],
|
|
46
|
+
expose_headers=["*"],
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
# Exception handlers
|
|
50
|
+
app.add_exception_handler(FileNotFoundError, file_not_found_handler) # type: ignore[arg-type]
|
|
51
|
+
app.add_exception_handler(ConflictError, conflict_error_handler) # type: ignore[arg-type]
|
|
52
|
+
# Note: ValueError is NOT handled globally to avoid masking internal processing errors.
|
|
53
|
+
# Endpoints should catch and handle ValueError explicitly when it represents user input validation.
|
|
54
|
+
# Note: ImportError is NOT handled globally to avoid masking genuine import bugs.
|
|
55
|
+
# The split_paths endpoint explicitly catches ImportError for missing optional dependencies.
|
|
56
|
+
app.add_exception_handler(ET.ParseError, parse_error_handler) # type: ignore[arg-type]
|
|
57
|
+
|
|
58
|
+
# Routers
|
|
59
|
+
app.include_router(create.router, prefix="/api")
|
|
60
|
+
app.include_router(add.router, prefix="/api")
|
|
61
|
+
app.include_router(remove.router, prefix="/api")
|
|
62
|
+
app.include_router(rename.router, prefix="/api")
|
|
63
|
+
app.include_router(list_router.router, prefix="/api")
|
|
64
|
+
app.include_router(extract.router, prefix="/api")
|
|
65
|
+
app.include_router(inspect.router, prefix="/api")
|
|
66
|
+
app.include_router(validate.router, prefix="/api")
|
|
67
|
+
app.include_router(split_paths.router, prefix="/api")
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
@app.get("/api/health", response_model=HealthResponse)
|
|
71
|
+
async def health() -> HealthResponse:
|
|
72
|
+
"""Health check endpoint.
|
|
73
|
+
|
|
74
|
+
Returns:
|
|
75
|
+
Service status and current package version.
|
|
76
|
+
"""
|
|
77
|
+
return HealthResponse(status="ok", version=__version__)
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
# Mount the pre-built Next.js static export when available.
|
|
81
|
+
# This is mounted AFTER all /api/* routes so API routes always take priority.
|
|
82
|
+
#
|
|
83
|
+
# Resolution order:
|
|
84
|
+
# 1. SVG2DRAWIO_UI_DIR env var (explicit override)
|
|
85
|
+
# 2. Bundled web/ directory next to this package (pip install SVG2DrawIOLib[web])
|
|
86
|
+
# 3. web-ui/out/ relative to CWD (source checkout / make start-web)
|
|
87
|
+
_env_ui = os.getenv("SVG2DRAWIO_UI_DIR")
|
|
88
|
+
if _env_ui:
|
|
89
|
+
_ui_dir = Path(_env_ui)
|
|
90
|
+
else:
|
|
91
|
+
_pkg_ui = Path(__file__).parent.parent / "web"
|
|
92
|
+
_ui_dir = _pkg_ui if _pkg_ui.is_dir() else Path("web-ui/out")
|
|
93
|
+
|
|
94
|
+
if _ui_dir.is_dir():
|
|
95
|
+
app.mount("/", StaticFiles(directory=_ui_dir, html=True), name="ui")
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""API response models."""
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"""Pydantic response models for API endpoints."""
|
|
2
|
+
|
|
3
|
+
from pydantic import BaseModel
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class HealthResponse(BaseModel):
|
|
7
|
+
"""Health check response."""
|
|
8
|
+
|
|
9
|
+
status: str
|
|
10
|
+
version: str
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class ListResponse(BaseModel):
|
|
14
|
+
"""Response for listing icons in a library."""
|
|
15
|
+
|
|
16
|
+
icon_names: list[str]
|
|
17
|
+
count: int
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class IconIssue(BaseModel):
|
|
21
|
+
"""A validation issue for a specific icon."""
|
|
22
|
+
|
|
23
|
+
severity: str # "error" or "warning"
|
|
24
|
+
icon: str
|
|
25
|
+
message: str
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class ValidationChecks(BaseModel):
|
|
29
|
+
"""Summary of validation checks performed."""
|
|
30
|
+
|
|
31
|
+
xml_structure: bool
|
|
32
|
+
json_format: bool
|
|
33
|
+
icon_count: int
|
|
34
|
+
icons_validated: int
|
|
35
|
+
icons_failed: int
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class ValidateResponse(BaseModel):
|
|
39
|
+
"""Response for library validation."""
|
|
40
|
+
|
|
41
|
+
valid: bool
|
|
42
|
+
errors: list[str]
|
|
43
|
+
warnings: list[str]
|
|
44
|
+
checks: ValidationChecks
|
|
45
|
+
icon_issues: list[IconIssue]
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class IconInfo(BaseModel):
|
|
49
|
+
"""Information about a single icon."""
|
|
50
|
+
|
|
51
|
+
name: str
|
|
52
|
+
width: float
|
|
53
|
+
height: float
|
|
54
|
+
shape_type: str | None = None
|
|
55
|
+
css_classes: list[str] = []
|
|
56
|
+
inline_styles: str | None = None
|
|
57
|
+
svg_content: str | None = None
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
class InspectResponse(BaseModel):
|
|
61
|
+
"""Response for inspecting library icons."""
|
|
62
|
+
|
|
63
|
+
icons: list[IconInfo]
|
|
64
|
+
count: int
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""API routers."""
|