codewave-openclaw-installer 2.1.13 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/install-lib.mjs +11 -0
- package/bin/install.mjs +59 -1
- package/package.json +12 -1
- package/skills/acceptance-doc-entry/SKILL.md +54 -1
- package/skills/ppt-master/SKILL.md +17 -390
- package/skills/ppt-master/projects/.gitkeep +0 -0
- package/skills/ppt-master/references/executor-base.md +4 -3
- package/skills/ppt-master/references/image-generator.md +6 -93
- package/skills/ppt-master/references/strategist.md +5 -8
- package/skills/ppt-master/scripts/README.md +1 -1
- package/skills/ppt-master/scripts/finalize_svg.py +0 -14
- package/skills/ppt-master/scripts/svg_quality_checker.py +8 -169
- package/skills/ppt-master/scripts/svg_to_pptx/pptx_builder.py +1 -7
- package/skills/ppt-master/scripts/svg_to_pptx/pptx_cli.py +0 -14
- package/skills/ppt-master/.env.example +0 -35
- package/skills/ppt-master/README.md +0 -90
- package/skills/ppt-master/audit_report_model_perf.md +0 -213
- package/skills/ppt-master/audit_report_portability.md +0 -90
- package/skills/ppt-master/audit_report_robustness.md +0 -192
- package/skills/ppt-master/audit_report_workflow.md +0 -233
- package/skills/ppt-master/fix_report_bid.md +0 -51
- package/skills/ppt-master/fix_report_scripts.md +0 -41
- package/skills/ppt-master/references/bid-content-example-netease.md +0 -815
- package/skills/ppt-master/references/bid-content-template.md +0 -390
- package/skills/ppt-master/references/bid-example-netease.md +0 -339
- package/skills/ppt-master/references/bid-presentation.md +0 -384
- package/skills/ppt-master/references/bid-svgs/03_toc.svg +0 -38
- package/skills/ppt-master/references/bid-svgs/04_chapter_company.svg +0 -7
- package/skills/ppt-master/references/bid-svgs/05_company_overview.svg +0 -28
- package/skills/ppt-master/references/bid-svgs/06_vision_business.svg +0 -45
- package/skills/ppt-master/references/bid-svgs/07_product_system.svg +0 -52
- package/skills/ppt-master/references/bid-svgs/08_codewave_timeline.svg +0 -29
- package/skills/ppt-master/references/bid-svgs/09_certifications.svg +0 -33
- package/skills/ppt-master/references/bid-svgs/10_client_logos.svg +0 -25
- package/skills/ppt-master/references/bid-svgs/11_brand_mission.svg +0 -14
- package/skills/ppt-master/references/bid-svgs/12_chapter_demand.svg +0 -7
- package/skills/ppt-master/references/bid-svgs/16_chapter_advantages.svg +0 -7
- package/skills/ppt-master/references/bid-svgs/18_platform_arch.svg +0 -24
- package/skills/ppt-master/references/bid-svgs/19_function_matrix.svg +0 -35
- package/skills/ppt-master/references/bid-svgs/20_dev_arch.svg +0 -29
- package/skills/ppt-master/references/bid-svgs/21_source_code.svg +0 -25
- package/skills/ppt-master/references/bid-svgs/22_ai_dev.svg +0 -27
- package/skills/ppt-master/references/bid-svgs/23_asset_market.svg +0 -33
- package/skills/ppt-master/references/bid-svgs/24_multi_org.svg +0 -28
- package/skills/ppt-master/references/bid-svgs/25_i18n.svg +0 -22
- package/skills/ppt-master/references/bid-svgs/26_multi_tenant.svg +0 -25
- package/skills/ppt-master/references/bid-svgs/27_integration.svg +0 -27
- package/skills/ppt-master/references/bid-svgs/28_permission.svg +0 -31
- package/skills/ppt-master/references/bid-svgs/29_security.svg +0 -25
- package/skills/ppt-master/references/bid-svgs/30_ai_capabilities.svg +0 -21
- package/skills/ppt-master/references/bid-svgs/31_product_combo.svg +0 -25
- package/skills/ppt-master/references/bid-svgs/32_digital_transform.svg +0 -28
- package/skills/ppt-master/references/bid-svgs/33_chapter_cases.svg +0 -7
- package/skills/ppt-master/references/bid-svgs/34_cummins_case.svg +0 -23
- package/skills/ppt-master/references/bid-svgs/35_cpq_cost.svg +0 -22
- package/skills/ppt-master/references/bid-svgs/36_tech_platform.svg +0 -18
- package/skills/ppt-master/references/bid-svgs/37_platform_value.svg +0 -24
- package/skills/ppt-master/references/bid-svgs/38_operation_plan.svg +0 -25
- package/skills/ppt-master/references/bid-svgs/39_zpmc_case.svg +0 -21
- package/skills/ppt-master/references/bid-svgs/40_zpmc_apps.svg +0 -23
- package/skills/ppt-master/references/bid-svgs/41_chapter_service.svg +0 -7
- package/skills/ppt-master/references/bid-svgs/42_tech_support.svg +0 -24
- package/skills/ppt-master/references/bid-svgs/43_knowledge_transfer.svg +0 -25
- package/skills/ppt-master/references/bid-svgs/44_operation_promotion.svg +0 -20
- package/skills/ppt-master/references/bid-svgs/45_custom_dev_guide.svg +0 -24
- package/skills/ppt-master/references/bid-svgs/46_sla_guarantee.svg +0 -18
- package/skills/ppt-master/references/bid-svgs/47_strategic_cooperation.svg +0 -25
- package/skills/ppt-master/references/bid-svgs/48_ecosystem.svg +0 -24
- package/skills/ppt-master/references/bid-svgs/49_chapter_delivery.svg +0 -23
- package/skills/ppt-master/references/bid-svgs/53_pm_intro.svg +0 -24
- package/skills/ppt-master/references/bid-svgs/54_after_sales.svg +0 -27
- package/skills/ppt-master/references/bid-svgs/55_ending.svg +0 -8
- package/skills/ppt-master/references/company_intro.md +0 -93
- package/skills/ppt-master/references/company_intro_images/slide1_img00.png +0 -0
- package/skills/ppt-master/references/company_intro_images/slide1_img01.png +0 -0
- package/skills/ppt-master/references/company_intro_images/slide1_img02.png +0 -0
- package/skills/ppt-master/references/company_intro_images/slide1_img03.png +0 -0
- package/skills/ppt-master/references/company_intro_images/slide1_img04.png +0 -0
- package/skills/ppt-master/references/company_intro_images/slide1_img05.png +0 -0
- package/skills/ppt-master/references/company_intro_images/slide1_img06.png +0 -0
- package/skills/ppt-master/references/company_intro_images/slide1_img07.png +0 -0
- package/skills/ppt-master/references/company_intro_images/slide1_img08.png +0 -0
- package/skills/ppt-master/references/company_intro_images/slide1_img09.png +0 -0
- package/skills/ppt-master/references/company_intro_images/slide1_img10.png +0 -0
- package/skills/ppt-master/references/company_intro_images/slide1_img11.png +0 -0
- package/skills/ppt-master/references/company_intro_images/slide1_img12.png +0 -0
- package/skills/ppt-master/references/company_intro_images/slide1_img13.png +0 -0
- package/skills/ppt-master/references/company_intro_images/slide1_img14.png +0 -0
- package/skills/ppt-master/references/company_intro_images/slide1_img15.png +0 -0
- package/skills/ppt-master/references/company_intro_images/slide1_img16.png +0 -0
- package/skills/ppt-master/references/company_intro_images/slide1_img17.png +0 -0
- package/skills/ppt-master/references/company_intro_images/slide1_img18.png +0 -0
- package/skills/ppt-master/references/company_intro_images/slide1_img19.png +0 -0
- package/skills/ppt-master/references/company_intro_images/slide1_img20.png +0 -0
- package/skills/ppt-master/references/company_intro_images/slide1_img21.png +0 -0
- package/skills/ppt-master/references/company_intro_images/slide1_img22.png +0 -0
- package/skills/ppt-master/references/company_intro_images/slide1_img23.png +0 -0
- package/skills/ppt-master/references/company_intro_images/slide1_img24.png +0 -0
- package/skills/ppt-master/references/company_intro_images/slide1_img25.png +0 -0
- package/skills/ppt-master/references/company_intro_images/slide1_img26.png +0 -0
- package/skills/ppt-master/references/company_intro_images/slide1_img27.png +0 -0
- package/skills/ppt-master/references/company_intro_images/slide1_img28.png +0 -0
- package/skills/ppt-master/references/company_intro_images/slide1_img29.png +0 -0
- package/skills/ppt-master/references/company_intro_images/slide2_img30.png +0 -0
- package/skills/ppt-master/references/company_intro_images/slide2_img31.jpg +0 -0
- package/skills/ppt-master/references/company_intro_images/slide3_img32.png +0 -0
- package/skills/ppt-master/references/company_intro_images/slide3_img33.png +0 -0
- package/skills/ppt-master/references/drawio-integration.md +0 -144
- package/skills/ppt-master/requirements.txt +0 -19
- package/skills/ppt-master/resources/backgrounds/chapter_bg.png +0 -0
- package/skills/ppt-master/resources/backgrounds/company_bg.png +0 -0
- package/skills/ppt-master/resources/backgrounds/cover_bg.png +0 -0
- package/skills/ppt-master/resources/backgrounds/index.json +0 -40
- package/skills/ppt-master/resources/backgrounds/tech_bg.png +0 -0
- package/skills/ppt-master/scripts/__pycache__/config.cpython-314.pyc +0 -0
- package/skills/ppt-master/scripts/__pycache__/error_helper.cpython-314.pyc +0 -0
- package/skills/ppt-master/scripts/__pycache__/pptx_animations.cpython-314.pyc +0 -0
- package/skills/ppt-master/scripts/__pycache__/project_utils.cpython-314.pyc +0 -0
- package/skills/ppt-master/scripts/arch_diagram.py +0 -370
- package/skills/ppt-master/scripts/bid_init.py +0 -79
- package/skills/ppt-master/scripts/drawio_gen.py +0 -366
- package/skills/ppt-master/scripts/drawio_to_svg.py +0 -458
- package/skills/ppt-master/scripts/image_backends/__pycache__/__init__.cpython-314.pyc +0 -0
- package/skills/ppt-master/scripts/image_backends/__pycache__/backend_aigw_gemini.cpython-314.pyc +0 -0
- package/skills/ppt-master/scripts/image_backends/__pycache__/backend_common.cpython-314.pyc +0 -0
- package/skills/ppt-master/scripts/svg_finalize/__pycache__/__init__.cpython-314.pyc +0 -0
- package/skills/ppt-master/scripts/svg_finalize/__pycache__/crop_images.cpython-314.pyc +0 -0
- package/skills/ppt-master/scripts/svg_finalize/__pycache__/embed_icons.cpython-314.pyc +0 -0
- package/skills/ppt-master/scripts/svg_finalize/__pycache__/embed_images.cpython-314.pyc +0 -0
- package/skills/ppt-master/scripts/svg_finalize/__pycache__/fix_image_aspect.cpython-314.pyc +0 -0
- package/skills/ppt-master/scripts/svg_finalize/__pycache__/flatten_tspan.cpython-314.pyc +0 -0
- package/skills/ppt-master/scripts/svg_finalize/__pycache__/svg_rect_to_path.cpython-314.pyc +0 -0
- package/skills/ppt-master/scripts/svg_page_gen.py +0 -871
- package/skills/ppt-master/scripts/svg_to_pptx/__pycache__/__init__.cpython-314.pyc +0 -0
- package/skills/ppt-master/scripts/svg_to_pptx/__pycache__/drawingml_context.cpython-314.pyc +0 -0
- package/skills/ppt-master/scripts/svg_to_pptx/__pycache__/drawingml_converter.cpython-314.pyc +0 -0
- package/skills/ppt-master/scripts/svg_to_pptx/__pycache__/drawingml_elements.cpython-314.pyc +0 -0
- package/skills/ppt-master/scripts/svg_to_pptx/__pycache__/drawingml_paths.cpython-314.pyc +0 -0
- package/skills/ppt-master/scripts/svg_to_pptx/__pycache__/drawingml_styles.cpython-314.pyc +0 -0
- package/skills/ppt-master/scripts/svg_to_pptx/__pycache__/drawingml_utils.cpython-314.pyc +0 -0
- package/skills/ppt-master/scripts/svg_to_pptx/__pycache__/pptx_builder.cpython-314.pyc +0 -0
- package/skills/ppt-master/scripts/svg_to_pptx/__pycache__/pptx_cli.cpython-314.pyc +0 -0
- package/skills/ppt-master/scripts/svg_to_pptx/__pycache__/pptx_dimensions.cpython-314.pyc +0 -0
- package/skills/ppt-master/scripts/svg_to_pptx/__pycache__/pptx_discovery.cpython-314.pyc +0 -0
- package/skills/ppt-master/scripts/svg_to_pptx/__pycache__/pptx_media.cpython-314.pyc +0 -0
- package/skills/ppt-master/scripts/svg_to_pptx/__pycache__/pptx_notes.cpython-314.pyc +0 -0
- package/skills/ppt-master/scripts/svg_to_pptx/__pycache__/pptx_slide_xml.cpython-314.pyc +0 -0
- /package/skills/ppt-master/templates/layouts//{316/243/342/225/225/302/241/317/203/302/242/342/225/234/317/204o/314/210/342/225/241/317/203/342/225/227/342/225/221_/317/203/342/225/225/342/225/225/316/246/302/272a/314/210 → 344/270/255/345/233/275/347/224/265/345/273/272_/345/270/270/350/247/204}/01_cover.svg" +0 -0
- /package/skills/ppt-master/templates/layouts//{316/243/342/225/225/302/241/317/203/302/242/342/225/234/317/204o/314/210/342/225/241/317/203/342/225/227/342/225/221_/317/203/342/225/225/342/225/225/316/246/302/272a/314/210 → 344/270/255/345/233/275/347/224/265/345/273/272_/345/270/270/350/247/204}/02_chapter.svg" +0 -0
- /package/skills/ppt-master/templates/layouts//{316/243/342/225/225/302/241/317/203/302/242/342/225/234/317/204o/314/210/342/225/241/317/203/342/225/227/342/225/221_/317/203/342/225/225/342/225/225/316/246/302/272a/314/210 → 344/270/255/345/233/275/347/224/265/345/273/272_/345/270/270/350/247/204}/02_toc.svg" +0 -0
- /package/skills/ppt-master/templates/layouts//{316/243/342/225/225/302/241/317/203/302/242/342/225/234/317/204o/314/210/342/225/241/317/203/342/225/227/342/225/221_/317/203/342/225/225/342/225/225/316/246/302/272a/314/210 → 344/270/255/345/233/275/347/224/265/345/273/272_/345/270/270/350/247/204}/03_content.svg" +0 -0
- /package/skills/ppt-master/templates/layouts//{316/243/342/225/225/302/241/317/203/302/242/342/225/234/317/204o/314/210/342/225/241/317/203/342/225/227/342/225/221_/317/203/342/225/225/342/225/225/316/246/302/272a/314/210 → 344/270/255/345/233/275/347/224/265/345/273/272_/345/270/270/350/247/204}/04_ending.svg" +0 -0
- /package/skills/ppt-master/templates/layouts//{316/243/342/225/225/302/241/317/203/302/242/342/225/234/317/204o/314/210/342/225/241/317/203/342/225/227/342/225/221_/317/203/342/225/225/342/225/225/316/246/302/272a/314/210 → 344/270/255/345/233/275/347/224/265/345/273/272_/345/270/270/350/247/204}/design_spec.md" +0 -0
- /package/skills/ppt-master/templates/layouts//{316/243/342/225/225/302/241/317/203/302/242/342/225/234/317/204o/314/210/342/225/241/317/203/342/225/227/342/225/221_/317/203/342/225/225/342/225/225/316/246/302/272a/314/210//316/243/342/225/225/302/241/317/203/302/242/342/225/234/302/265/342/226/221/342/224/244/317/203e/314/200i/314/201logo.png" → 344/270/255/345/233/275/347/224/265/345/273/272_/345/270/270/350/247/204//344/270/255/345/233/275/346/260/264/345/212/241logo.png"} +0 -0
- /package/skills/ppt-master/templates/layouts//{316/243/342/225/225/302/241/317/203/302/242/342/225/234/317/204o/314/210/342/225/241/317/203/342/225/227/342/225/221_/317/203/342/225/225/342/225/225/316/246/302/272a/314/210//317/203i/314/200A/314/210/316/243/342/225/225/302/243/316/230O/314/210o/314/201logo.png" → 344/270/255/345/233/275/347/224/265/345/273/272_/345/270/270/350/247/204//345/215/216/344/270/234/351/231/242logo.png"} +0 -0
- /package/skills/ppt-master/templates/layouts//{316/243/342/225/225/302/241/317/203/302/242/342/225/234/317/204o/314/210/342/225/241/317/203/342/225/227/342/225/221_/317/203/342/225/225/342/225/225/316/246/302/272a/314/210//302/265/342/226/221/342/224/244/317/204o/314/210/342/225/241/316/243/342/225/225e/314/210/317/203/342/226/222C/314/247logo.png" → 344/270/255/345/233/275/347/224/265/345/273/272_/345/270/270/350/247/204//346/260/264/347/224/265/344/270/211/345/261/200logo.png"} +0 -0
- /package/skills/ppt-master/templates/layouts//{316/243/342/225/225/302/241/317/203/302/242/342/225/234/317/204o/314/210/342/225/241/317/203/342/225/227/342/225/221_/317/203/342/225/225/342/225/225/316/246/302/272a/314/210//317/204o/314/210/342/225/241/317/203/342/225/227/342/225/221logo.png" → 344/270/255/345/233/275/347/224/265/345/273/272_/345/270/270/350/247/204//347/224/265/345/273/272logo.png"} +0 -0
- /package/skills/ppt-master/templates/layouts//{316/243/342/225/225/302/241/317/203/302/242/342/225/234/317/204o/314/210/342/225/241/317/203/342/225/227/342/225/221_/317/204A/314/210/342/226/221/316/243/342/225/227u/314/201 → 344/270/255/345/233/275/347/224/265/345/273/272_/347/216/260/344/273/243}/01_cover.svg" +0 -0
- /package/skills/ppt-master/templates/layouts//{316/243/342/225/225/302/241/317/203/302/242/342/225/234/317/204o/314/210/342/225/241/317/203/342/225/227/342/225/221_/317/204A/314/210/342/226/221/316/243/342/225/227u/314/201 → 344/270/255/345/233/275/347/224/265/345/273/272_/347/216/260/344/273/243}/02_chapter.svg" +0 -0
- /package/skills/ppt-master/templates/layouts//{316/243/342/225/225/302/241/317/203/302/242/342/225/234/317/204o/314/210/342/225/241/317/203/342/225/227/342/225/221_/317/204A/314/210/342/226/221/316/243/342/225/227u/314/201 → 344/270/255/345/233/275/347/224/265/345/273/272_/347/216/260/344/273/243}/02_toc.svg" +0 -0
- /package/skills/ppt-master/templates/layouts//{316/243/342/225/225/302/241/317/203/302/242/342/225/234/317/204o/314/210/342/225/241/317/203/342/225/227/342/225/221_/317/204A/314/210/342/226/221/316/243/342/225/227u/314/201 → 344/270/255/345/233/275/347/224/265/345/273/272_/347/216/260/344/273/243}/03_content.svg" +0 -0
- /package/skills/ppt-master/templates/layouts//{316/243/342/225/225/302/241/317/203/302/242/342/225/234/317/204o/314/210/342/225/241/317/203/342/225/227/342/225/221_/317/204A/314/210/342/226/221/316/243/342/225/227u/314/201 → 344/270/255/345/233/275/347/224/265/345/273/272_/347/216/260/344/273/243}/04_ending.svg" +0 -0
- /package/skills/ppt-master/templates/layouts//{316/243/342/225/225/302/241/317/203/302/242/342/225/234/317/204o/314/210/342/225/241/317/203/342/225/227/342/225/221_/317/204A/314/210/342/226/221/316/243/342/225/227u/314/201 → 344/270/255/345/233/275/347/224/265/345/273/272_/347/216/260/344/273/243}/design_spec.md" +0 -0
- /package/skills/ppt-master/templates/layouts//{316/243/342/225/225/302/241/317/203/302/242/342/225/234/317/204o/314/210/342/225/241/317/203/342/225/227/342/225/221_/317/204A/314/210/342/226/221/316/243/342/225/227u/314/201//316/243/342/225/225/302/241/317/203/302/242/342/225/234/302/265/342/226/221/342/224/244/317/203e/314/200i/314/201logo.png" → 344/270/255/345/233/275/347/224/265/345/273/272_/347/216/260/344/273/243//344/270/255/345/233/275/346/260/264/345/212/241logo.png"} +0 -0
- /package/skills/ppt-master/templates/layouts//{316/243/342/225/225/302/241/317/203/302/242/342/225/234/317/204o/314/210/342/225/241/317/203/342/225/227/342/225/221_/317/204A/314/210/342/226/221/316/243/342/225/227u/314/201//317/203i/314/200A/314/210/316/243/342/225/225/302/243/316/230O/314/210o/314/201logo.png" → 344/270/255/345/233/275/347/224/265/345/273/272_/347/216/260/344/273/243//345/215/216/344/270/234/351/231/242logo.png"} +0 -0
- /package/skills/ppt-master/templates/layouts//{316/243/342/225/225/302/241/317/203/302/242/342/225/234/317/204o/314/210/342/225/241/317/203/342/225/227/342/225/221_/317/204A/314/210/342/226/221/316/243/342/225/227u/314/201//302/265/342/226/221/342/224/244/317/204o/314/210/342/225/241/316/243/342/225/225e/314/210/317/203/342/226/222C/314/247logo.png" → 344/270/255/345/233/275/347/224/265/345/273/272_/347/216/260/344/273/243//346/260/264/347/224/265/344/270/211/345/261/200logo.png"} +0 -0
- /package/skills/ppt-master/templates/layouts//{316/243/342/225/225/302/241/317/203/302/242/342/225/234/317/204o/314/210/342/225/241/317/203/342/225/227/342/225/221_/317/204A/314/210/342/226/221/316/243/342/225/227u/314/201//317/204o/314/210/342/225/241/317/203/342/225/227/342/225/221logo.png" → 344/270/255/345/233/275/347/224/265/345/273/272_/347/216/260/344/273/243//347/224/265/345/273/272logo.png"} +0 -0
- /package/skills/ppt-master/templates/layouts//{316/243/342/225/225/302/241/302/265/342/226/222/342/225/234/317/204a/314/201o/314/210_/317/203o/314/200a/314/212/317/203e/314/200i/314/201 → 344/270/255/346/261/275/347/240/224_/345/225/206/345/212/241}/01_cover.svg" +0 -0
- /package/skills/ppt-master/templates/layouts//{316/243/342/225/225/302/241/302/265/342/226/222/342/225/234/317/204a/314/201o/314/210_/317/203o/314/200a/314/212/317/203e/314/200i/314/201 → 344/270/255/346/261/275/347/240/224_/345/225/206/345/212/241}/02_chapter.svg" +0 -0
- /package/skills/ppt-master/templates/layouts//{316/243/342/225/225/302/241/302/265/342/226/222/342/225/234/317/204a/314/201o/314/210_/317/203o/314/200a/314/212/317/203e/314/200i/314/201 → 344/270/255/346/261/275/347/240/224_/345/225/206/345/212/241}/02_toc.svg" +0 -0
- /package/skills/ppt-master/templates/layouts//{316/243/342/225/225/302/241/302/265/342/226/222/342/225/234/317/204a/314/201o/314/210_/317/203o/314/200a/314/212/317/203e/314/200i/314/201 → 344/270/255/346/261/275/347/240/224_/345/225/206/345/212/241}/03_content.svg" +0 -0
- /package/skills/ppt-master/templates/layouts//{316/243/342/225/225/302/241/302/265/342/226/222/342/225/234/317/204a/314/201o/314/210_/317/203o/314/200a/314/212/317/203e/314/200i/314/201 → 344/270/255/346/261/275/347/240/224_/345/225/206/345/212/241}/04_ending.svg" +0 -0
- /package/skills/ppt-master/templates/layouts//{316/243/342/225/225/302/241/302/265/342/226/222/342/225/234/317/204a/314/201o/314/210_/317/203o/314/200a/314/212/317/203e/314/200i/314/201 → 344/270/255/346/261/275/347/240/224_/345/225/206/345/212/241}/design_spec.md" +0 -0
- /package/skills/ppt-master/templates/layouts//{316/243/342/225/225/302/241/302/265/342/226/222/342/225/234/317/204a/314/201o/314/210_/317/203o/314/200a/314/212/317/203e/314/200i/314/201//317/203A/314/212/342/224/202/316/243/342/225/225e/314/200/316/246/302/272/303/206 logo.png" → 344/270/255/346/261/275/347/240/224_/345/225/206/345/212/241//345/217/263/344/270/212/350/247/222 logo.png"} +0 -0
- /package/skills/ppt-master/templates/layouts//{316/243/342/225/225/302/241/302/265/342/226/222/342/225/234/317/204a/314/201o/314/210_/317/203o/314/200a/314/212/317/203e/314/200i/314/201//317/203n/314/203/302/272/317/203/342/202/247i/314/210 logo.png" → 344/270/255/346/261/275/347/240/224_/345/225/206/345/212/241//345/244/247/345/236/213 logo.png"} +0 -0
- /package/skills/ppt-master/templates/layouts//{316/243/342/225/225/302/241/302/265/342/226/222/342/225/234/317/204a/314/201o/314/210_/317/203/342/225/225/342/225/225/316/246/302/272a/314/210 → 344/270/255/346/261/275/347/240/224_/345/270/270/350/247/204}/01_cover.svg" +0 -0
- /package/skills/ppt-master/templates/layouts//{316/243/342/225/225/302/241/302/265/342/226/222/342/225/234/317/204a/314/201o/314/210_/317/203/342/225/225/342/225/225/316/246/302/272a/314/210 → 344/270/255/346/261/275/347/240/224_/345/270/270/350/247/204}/02_chapter.svg" +0 -0
- /package/skills/ppt-master/templates/layouts//{316/243/342/225/225/302/241/302/265/342/226/222/342/225/234/317/204a/314/201o/314/210_/317/203/342/225/225/342/225/225/316/246/302/272a/314/210 → 344/270/255/346/261/275/347/240/224_/345/270/270/350/247/204}/02_toc.svg" +0 -0
- /package/skills/ppt-master/templates/layouts//{316/243/342/225/225/302/241/302/265/342/226/222/342/225/234/317/204a/314/201o/314/210_/317/203/342/225/225/342/225/225/316/246/302/272a/314/210 → 344/270/255/346/261/275/347/240/224_/345/270/270/350/247/204}/03_content.svg" +0 -0
- /package/skills/ppt-master/templates/layouts//{316/243/342/225/225/302/241/302/265/342/226/222/342/225/234/317/204a/314/201o/314/210_/317/203/342/225/225/342/225/225/316/246/302/272a/314/210 → 344/270/255/346/261/275/347/240/224_/345/270/270/350/247/204}/04_ending.svg" +0 -0
- /package/skills/ppt-master/templates/layouts//{316/243/342/225/225/302/241/302/265/342/226/222/342/225/234/317/204a/314/201o/314/210_/317/203/342/225/225/342/225/225/316/246/302/272a/314/210 → 344/270/255/346/261/275/347/240/224_/345/270/270/350/247/204}/design_spec.md" +0 -0
- /package/skills/ppt-master/templates/layouts//{316/243/342/225/225/302/241/302/265/342/226/222/342/225/234/317/204a/314/201o/314/210_/317/203/342/225/225/342/225/225/316/246/302/272a/314/210//317/203A/314/212/342/224/202/316/243/342/225/225e/314/200/316/246/302/272/303/206 logo.png" → 344/270/255/346/261/275/347/240/224_/345/270/270/350/247/204//345/217/263/344/270/212/350/247/222 logo.png"} +0 -0
- /package/skills/ppt-master/templates/layouts//{316/243/342/225/225/302/241/302/265/342/226/222/342/225/234/317/204a/314/201o/314/210_/317/203/342/225/225/342/225/225/316/246/302/272a/314/210//317/203n/314/203/302/272/317/203/342/202/247i/314/210 logo.png" → 344/270/255/346/261/275/347/240/224_/345/270/270/350/247/204//345/244/247/345/236/213 logo.png"} +0 -0
- /package/skills/ppt-master/templates/layouts//{316/243/342/225/225/302/241/302/265/342/226/222/342/225/234/317/204a/314/201o/314/210_/317/204A/314/210/342/226/221/316/243/342/225/227u/314/201 → 344/270/255/346/261/275/347/240/224_/347/216/260/344/273/243}/01_cover.svg" +0 -0
- /package/skills/ppt-master/templates/layouts//{316/243/342/225/225/302/241/302/265/342/226/222/342/225/234/317/204a/314/201o/314/210_/317/204A/314/210/342/226/221/316/243/342/225/227u/314/201 → 344/270/255/346/261/275/347/240/224_/347/216/260/344/273/243}/02_chapter.svg" +0 -0
- /package/skills/ppt-master/templates/layouts//{316/243/342/225/225/302/241/302/265/342/226/222/342/225/234/317/204a/314/201o/314/210_/317/204A/314/210/342/226/221/316/243/342/225/227u/314/201 → 344/270/255/346/261/275/347/240/224_/347/216/260/344/273/243}/02_toc.svg" +0 -0
- /package/skills/ppt-master/templates/layouts//{316/243/342/225/225/302/241/302/265/342/226/222/342/225/234/317/204a/314/201o/314/210_/317/204A/314/210/342/226/221/316/243/342/225/227u/314/201 → 344/270/255/346/261/275/347/240/224_/347/216/260/344/273/243}/03_content.svg" +0 -0
- /package/skills/ppt-master/templates/layouts//{316/243/342/225/225/302/241/302/265/342/226/222/342/225/234/317/204a/314/201o/314/210_/317/204A/314/210/342/226/221/316/243/342/225/227u/314/201 → 344/270/255/346/261/275/347/240/224_/347/216/260/344/273/243}/04_ending.svg" +0 -0
- /package/skills/ppt-master/templates/layouts//{316/243/342/225/225/302/241/302/265/342/226/222/342/225/234/317/204a/314/201o/314/210_/317/204A/314/210/342/226/221/316/243/342/225/227u/314/201 → 344/270/255/346/261/275/347/240/224_/347/216/260/344/273/243}/design_spec.md" +0 -0
- /package/skills/ppt-master/templates/layouts//{316/243/342/225/225/302/241/302/265/342/226/222/342/225/234/317/204a/314/201o/314/210_/317/204A/314/210/342/226/221/316/243/342/225/227u/314/201//317/203A/314/212/342/224/202/316/243/342/225/225e/314/200/316/246/302/272/303/206 logo.png" → 344/270/255/346/261/275/347/240/224_/347/216/260/344/273/243//345/217/263/344/270/212/350/247/222 logo.png"} +0 -0
- /package/skills/ppt-master/templates/layouts//{316/243/342/225/225/302/241/302/265/342/226/222/342/225/234/317/204a/314/201o/314/210_/317/204A/314/210/342/226/221/316/243/342/225/227u/314/201//317/203n/314/203/302/272/317/203/342/202/247i/314/210 logo.png" → 344/270/255/346/261/275/347/240/224_/347/216/260/344/273/243//345/244/247/345/236/213 logo.png"} +0 -0
- /package/skills/ppt-master/templates/layouts//{302/265i/314/210/302/242/317/203o/314/200a/314/212/316/230o/314/202/342/225/242/316/246i/314/201i/314/202 → 346/213/233/345/225/206/351/223/266/350/241/214}/01_cover.svg" +0 -0
- /package/skills/ppt-master/templates/layouts//{302/265i/314/210/302/242/317/203o/314/200a/314/212/316/230o/314/202/342/225/242/316/246i/314/201i/314/202 → 346/213/233/345/225/206/351/223/266/350/241/214}/02_chapter.svg" +0 -0
- /package/skills/ppt-master/templates/layouts//{302/265i/314/210/302/242/317/203o/314/200a/314/212/316/230o/314/202/342/225/242/316/246i/314/201i/314/202 → 346/213/233/345/225/206/351/223/266/350/241/214}/02_toc.svg" +0 -0
- /package/skills/ppt-master/templates/layouts//{302/265i/314/210/302/242/317/203o/314/200a/314/212/316/230o/314/202/342/225/242/316/246i/314/201i/314/202 → 346/213/233/345/225/206/351/223/266/350/241/214}/03_content.svg" +0 -0
- /package/skills/ppt-master/templates/layouts//{302/265i/314/210/302/242/317/203o/314/200a/314/212/316/230o/314/202/342/225/242/316/246i/314/201i/314/202 → 346/213/233/345/225/206/351/223/266/350/241/214}/04_ending.svg" +0 -0
- /package/skills/ppt-master/templates/layouts//{302/265i/314/210/302/242/317/203o/314/200a/314/212/316/230o/314/202/342/225/242/316/246i/314/201i/314/202 → 346/213/233/345/225/206/351/223/266/350/241/214}/design_spec.md" +0 -0
- /package/skills/ppt-master/templates/layouts//{302/265i/314/210/302/242/317/203o/314/200a/314/212/316/230o/314/202/342/225/242/316/246i/314/201i/314/202//302/265i/314/210/302/242/317/203o/314/200a/314/212/316/230o/314/202/342/225/242/316/246i/314/201i/314/202/317/203a/314/200/302/274/317/203A/314/212/342/225/225/316/230c/314/247/303/246/316/246/342/202/247i/314/200.png" → 346/213/233/345/225/206/351/223/266/350/241/214//346/213/233/345/225/206/351/223/266/350/241/214/345/205/254/345/217/270/351/207/221/350/236/215.png"} +0 -0
- /package/skills/ppt-master/templates/layouts//{317/204/302/272/303/246/302/265e/314/200C/314/247/316/246o/314/202/302/245/317/203o/314/200a/314/212/317/203e/314/200i/314/201 → 347/247/221/346/212/200/350/223/235/345/225/206/345/212/241}/01_cover.svg" +0 -0
- /package/skills/ppt-master/templates/layouts//{317/204/302/272/303/246/302/265e/314/200C/314/247/316/246o/314/202/302/245/317/203o/314/200a/314/212/317/203e/314/200i/314/201 → 347/247/221/346/212/200/350/223/235/345/225/206/345/212/241}/02_chapter.svg" +0 -0
- /package/skills/ppt-master/templates/layouts//{317/204/302/272/303/246/302/265e/314/200C/314/247/316/246o/314/202/302/245/317/203o/314/200a/314/212/317/203e/314/200i/314/201 → 347/247/221/346/212/200/350/223/235/345/225/206/345/212/241}/02_toc.svg" +0 -0
- /package/skills/ppt-master/templates/layouts//{317/204/302/272/303/246/302/265e/314/200C/314/247/316/246o/314/202/302/245/317/203o/314/200a/314/212/317/203e/314/200i/314/201 → 347/247/221/346/212/200/350/223/235/345/225/206/345/212/241}/03_content.svg" +0 -0
- /package/skills/ppt-master/templates/layouts//{317/204/302/272/303/246/302/265e/314/200C/314/247/316/246o/314/202/302/245/317/203o/314/200a/314/212/317/203e/314/200i/314/201 → 347/247/221/346/212/200/350/223/235/345/225/206/345/212/241}/04_ending.svg" +0 -0
- /package/skills/ppt-master/templates/layouts//{317/204/302/272/303/246/302/265e/314/200C/314/247/316/246o/314/202/302/245/317/203o/314/200a/314/212/317/203e/314/200i/314/201 → 347/247/221/346/212/200/350/223/235/345/225/206/345/212/241}/design_spec.md" +0 -0
- /package/skills/ppt-master/templates/layouts/{Technology Blue Business/01_cover.svg → /351/207/215/345/272/206/345/244/247/345/255/246/01_cover.svg"} +0 -0
- /package/skills/ppt-master/templates/layouts/{Technology Blue Business/02_chapter.svg → /351/207/215/345/272/206/345/244/247/345/255/246/02_chapter.svg"} +0 -0
- /package/skills/ppt-master/templates/layouts/{Technology Blue Business/02_toc.svg → /351/207/215/345/272/206/345/244/247/345/255/246/02_toc.svg"} +0 -0
- /package/skills/ppt-master/templates/layouts/{Technology Blue Business/03_content.svg → /351/207/215/345/272/206/345/244/247/345/255/246/03_content.svg"} +0 -0
- /package/skills/ppt-master/templates/layouts/{Technology Blue Business/04_ending.svg → /351/207/215/345/272/206/345/244/247/345/255/246/04_ending.svg"} +0 -0
- /package/skills/ppt-master/templates/layouts/{Technology Blue Business/design_spec.md → /351/207/215/345/272/206/345/244/247/345/255/246/design_spec.md"} +0 -0
- /package/skills/ppt-master/templates/layouts/{Technology Blue Business//316/230c/314/247i/314/200/317/203/342/225/221a/314/212/317/203n/314/203/302/272/317/203/302/241/302/252logo.png" → /351/207/215/345/272/206/345/244/247/345/255/246//351/207/215/345/272/206/345/244/247/345/255/246logo.png"} +0 -0
- /package/skills/ppt-master/templates/layouts/{Technology Blue Business//316/230c/314/247i/314/200/317/203/342/225/221a/314/212/317/203n/314/203/302/272/317/203/302/241/302/252logo2.png" → /351/207/215/345/272/206/345/244/247/345/255/246//351/207/215/345/272/206/345/244/247/345/255/246logo2.png"} +0 -0
|
@@ -1,458 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""
|
|
3
|
-
drawio_to_svg.py - Convert draw.io XML to PPT Master compatible SVG.
|
|
4
|
-
|
|
5
|
-
Parses a .drawio file and renders it as a standalone SVG at 1280x720
|
|
6
|
-
(16:9 PPT format), compatible with the PPT Master pipeline.
|
|
7
|
-
|
|
8
|
-
This does NOT require draw.io Desktop installed. It directly parses
|
|
9
|
-
the mxGraph XML and renders nodes/edges as SVG elements.
|
|
10
|
-
|
|
11
|
-
Usage:
|
|
12
|
-
python drawio_to_svg.py <input.drawio> -o <output.svg>
|
|
13
|
-
python drawio_to_svg.py <input.drawio> -o <output.svg> --width 1280 --height 720
|
|
14
|
-
python drawio_to_svg.py <input.drawio> -o <output.svg> --title "System Architecture"
|
|
15
|
-
python drawio_to_svg.py <input.drawio> -o <output.svg> --background "#ffffff" --padding 40
|
|
16
|
-
"""
|
|
17
|
-
|
|
18
|
-
import sys
|
|
19
|
-
import re
|
|
20
|
-
import argparse
|
|
21
|
-
import xml.etree.ElementTree as ET
|
|
22
|
-
from dataclasses import dataclass, field
|
|
23
|
-
from typing import Optional
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
@dataclass
|
|
27
|
-
class NodeInfo:
|
|
28
|
-
id: str
|
|
29
|
-
label: str
|
|
30
|
-
x: float
|
|
31
|
-
y: float
|
|
32
|
-
width: float
|
|
33
|
-
height: float
|
|
34
|
-
style: dict = field(default_factory=dict)
|
|
35
|
-
parent: str = "1"
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
@dataclass
|
|
39
|
-
class EdgeInfo:
|
|
40
|
-
id: str
|
|
41
|
-
label: str
|
|
42
|
-
source: str
|
|
43
|
-
target: str
|
|
44
|
-
style: dict = field(default_factory=dict)
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
def parse_style(style_str: str) -> dict:
|
|
48
|
-
"""Parse mxGraph style string into dict."""
|
|
49
|
-
result = {}
|
|
50
|
-
if not style_str:
|
|
51
|
-
return result
|
|
52
|
-
for part in style_str.rstrip(";").split(";"):
|
|
53
|
-
if "=" in part:
|
|
54
|
-
k, v = part.split("=", 1)
|
|
55
|
-
result[k.strip()] = v.strip()
|
|
56
|
-
elif part.strip():
|
|
57
|
-
result[part.strip()] = True
|
|
58
|
-
return result
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
def parse_drawio(filepath: str):
|
|
62
|
-
"""Parse a .drawio file and return nodes and edges."""
|
|
63
|
-
with open(filepath, "r", encoding="utf-8") as f:
|
|
64
|
-
tree = ET.parse(f)
|
|
65
|
-
root = tree.getroot()
|
|
66
|
-
|
|
67
|
-
nodes = {}
|
|
68
|
-
edges = []
|
|
69
|
-
groups = {}
|
|
70
|
-
|
|
71
|
-
for diagram in root.findall(".//diagram"):
|
|
72
|
-
for cell in diagram.iter("mxCell"):
|
|
73
|
-
cell_id = cell.get("id", "")
|
|
74
|
-
if cell_id in ("0", "1"):
|
|
75
|
-
continue
|
|
76
|
-
|
|
77
|
-
parent = cell.get("parent", "1")
|
|
78
|
-
style = parse_style(cell.get("style", ""))
|
|
79
|
-
value = cell.get("value", "")
|
|
80
|
-
geo = cell.find("mxGeometry")
|
|
81
|
-
|
|
82
|
-
if cell.get("vertex") == "1":
|
|
83
|
-
x = float(geo.get("x", "0")) if geo is not None else 0
|
|
84
|
-
y = float(geo.get("y", "0")) if geo is not None else 0
|
|
85
|
-
w = float(geo.get("width", "120")) if geo is not None else 120
|
|
86
|
-
h = float(geo.get("height", "60")) if geo is not None else 60
|
|
87
|
-
|
|
88
|
-
if "container" in style:
|
|
89
|
-
groups[cell_id] = NodeInfo(cell_id, value, x, y, w, h, style, parent)
|
|
90
|
-
else:
|
|
91
|
-
nodes[cell_id] = NodeInfo(cell_id, value, x, y, w, h, style, parent)
|
|
92
|
-
|
|
93
|
-
elif cell.get("edge") == "1":
|
|
94
|
-
edges.append(EdgeInfo(cell_id, value,
|
|
95
|
-
cell.get("source", ""),
|
|
96
|
-
cell.get("target", ""),
|
|
97
|
-
style))
|
|
98
|
-
|
|
99
|
-
# Also check <object> elements (N2G format)
|
|
100
|
-
for obj in diagram.iter("object"):
|
|
101
|
-
obj_id = obj.get("id", "")
|
|
102
|
-
value = obj.get("label", "")
|
|
103
|
-
inner = obj.find("mxCell")
|
|
104
|
-
if inner is None:
|
|
105
|
-
continue
|
|
106
|
-
|
|
107
|
-
style = parse_style(inner.get("style", ""))
|
|
108
|
-
parent = inner.get("parent", "1")
|
|
109
|
-
geo = inner.find("mxGeometry")
|
|
110
|
-
|
|
111
|
-
if inner.get("vertex") == "1":
|
|
112
|
-
x = float(geo.get("x", "0")) if geo is not None else 0
|
|
113
|
-
y = float(geo.get("y", "0")) if geo is not None else 0
|
|
114
|
-
w = float(geo.get("width", "120")) if geo is not None else 120
|
|
115
|
-
h = float(geo.get("height", "60")) if geo is not None else 60
|
|
116
|
-
nodes[obj_id] = NodeInfo(obj_id, value, x, y, w, h, style, parent)
|
|
117
|
-
|
|
118
|
-
elif inner.get("edge") == "1":
|
|
119
|
-
edges.append(EdgeInfo(obj_id, value,
|
|
120
|
-
inner.get("source", obj.get("source", "")),
|
|
121
|
-
inner.get("target", obj.get("target", "")),
|
|
122
|
-
style))
|
|
123
|
-
|
|
124
|
-
# Resolve relative positions for grouped nodes
|
|
125
|
-
for nid, node in nodes.items():
|
|
126
|
-
if node.parent in groups:
|
|
127
|
-
g = groups[node.parent]
|
|
128
|
-
node.x += g.x
|
|
129
|
-
node.y += g.y
|
|
130
|
-
|
|
131
|
-
return nodes, edges, groups
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
def color_from_style(style: dict, key: str, default: str) -> str:
|
|
135
|
-
return style.get(key, default)
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
def get_shape_type(style: dict) -> str:
|
|
139
|
-
"""Determine shape type from style dict."""
|
|
140
|
-
shape = style.get("shape", "")
|
|
141
|
-
if "cylinder" in shape or "cylinder3" in str(style):
|
|
142
|
-
return "cylinder"
|
|
143
|
-
if "cloud" in shape:
|
|
144
|
-
return "cloud"
|
|
145
|
-
if "rhombus" in style or "diamond" in str(style):
|
|
146
|
-
return "diamond"
|
|
147
|
-
if "ellipse" in style:
|
|
148
|
-
return "ellipse"
|
|
149
|
-
if "hexagon" in shape:
|
|
150
|
-
return "hexagon"
|
|
151
|
-
if style.get("rounded"):
|
|
152
|
-
return "rounded"
|
|
153
|
-
return "rect"
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
def svg_shape(node: NodeInfo, svg_lines: list):
|
|
157
|
-
"""Render a node as SVG elements."""
|
|
158
|
-
x, y, w, h = node.x, node.y, node.width, node.height
|
|
159
|
-
fill = color_from_style(node.style, "fillColor", "#dae8fc")
|
|
160
|
-
stroke = color_from_style(node.style, "strokeColor", "#6c8ebf")
|
|
161
|
-
shape = get_shape_type(node.style)
|
|
162
|
-
stroke_w = "1.5"
|
|
163
|
-
|
|
164
|
-
if shape == "cylinder":
|
|
165
|
-
# Cylinder: rect + top/bottom ellipse
|
|
166
|
-
ry = min(12, h * 0.15)
|
|
167
|
-
svg_lines.append(f' <rect x="{x}" y="{y + ry}" width="{w}" height="{h - 2*ry}" '
|
|
168
|
-
f'fill="{fill}" stroke="{stroke}" stroke-width="{stroke_w}" />')
|
|
169
|
-
svg_lines.append(f' <ellipse cx="{x + w/2}" cy="{y + ry}" rx="{w/2}" ry="{ry}" '
|
|
170
|
-
f'fill="{fill}" stroke="{stroke}" stroke-width="{stroke_w}" />')
|
|
171
|
-
svg_lines.append(f' <ellipse cx="{x + w/2}" cy="{y + h - ry}" rx="{w/2}" ry="{ry}" '
|
|
172
|
-
f'fill="{fill}" stroke="{stroke}" stroke-width="{stroke_w}" />')
|
|
173
|
-
elif shape == "ellipse" or shape == "cloud":
|
|
174
|
-
svg_lines.append(f' <ellipse cx="{x + w/2}" cy="{y + h/2}" rx="{w/2}" ry="{h/2}" '
|
|
175
|
-
f'fill="{fill}" stroke="{stroke}" stroke-width="{stroke_w}" />')
|
|
176
|
-
elif shape == "diamond":
|
|
177
|
-
cx, cy = x + w/2, y + h/2
|
|
178
|
-
points = f"{cx},{y} {x+w},{cy} {cx},{y+h} {x},{cy}"
|
|
179
|
-
svg_lines.append(f' <polygon points="{points}" '
|
|
180
|
-
f'fill="{fill}" stroke="{stroke}" stroke-width="{stroke_w}" />')
|
|
181
|
-
elif shape == "hexagon":
|
|
182
|
-
dx = w * 0.15
|
|
183
|
-
points = f"{x+dx},{y} {x+w-dx},{y} {x+w},{y+h/2} {x+w-dx},{y+h} {x+dx},{y+h} {x},{y+h/2}"
|
|
184
|
-
svg_lines.append(f' <polygon points="{points}" '
|
|
185
|
-
f'fill="{fill}" stroke="{stroke}" stroke-width="{stroke_w}" />')
|
|
186
|
-
elif shape == "rounded":
|
|
187
|
-
r = min(12, w * 0.1, h * 0.2)
|
|
188
|
-
svg_lines.append(f' <rect x="{x}" y="{y}" width="{w}" height="{h}" rx="{r}" ry="{r}" '
|
|
189
|
-
f'fill="{fill}" stroke="{stroke}" stroke-width="{stroke_w}" />')
|
|
190
|
-
else:
|
|
191
|
-
svg_lines.append(f' <rect x="{x}" y="{y}" width="{w}" height="{h}" '
|
|
192
|
-
f'fill="{fill}" stroke="{stroke}" stroke-width="{stroke_w}" />')
|
|
193
|
-
|
|
194
|
-
# Label
|
|
195
|
-
label = node.label.replace("&", "&").replace("<", "<").replace(">", ">")
|
|
196
|
-
if label:
|
|
197
|
-
font_size = 12
|
|
198
|
-
svg_lines.append(f' <text x="{x + w/2}" y="{y + h/2}" '
|
|
199
|
-
f'text-anchor="middle" dominant-baseline="central" '
|
|
200
|
-
f'font-family="Helvetica, Arial, sans-serif" font-size="{font_size}" '
|
|
201
|
-
f'fill="#333333">{label}</text>')
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
def svg_edge(edge: EdgeInfo, nodes: dict, svg_lines: list):
|
|
205
|
-
"""Render an edge as orthogonal polyline for cleaner look."""
|
|
206
|
-
src = nodes.get(edge.source)
|
|
207
|
-
tgt = nodes.get(edge.target)
|
|
208
|
-
if not src or not tgt:
|
|
209
|
-
return
|
|
210
|
-
|
|
211
|
-
# Center points
|
|
212
|
-
sx = src.x + src.width / 2
|
|
213
|
-
sy = src.y + src.height / 2
|
|
214
|
-
tx = tgt.x + tgt.width / 2
|
|
215
|
-
ty = tgt.y + tgt.height / 2
|
|
216
|
-
|
|
217
|
-
stroke = color_from_style(edge.style, "strokeColor", "#666666")
|
|
218
|
-
dash = ""
|
|
219
|
-
if edge.style.get("dashed"):
|
|
220
|
-
pattern = edge.style.get("dashPattern", "8 8")
|
|
221
|
-
dash = f' stroke-dasharray="{pattern}"'
|
|
222
|
-
|
|
223
|
-
# Determine best connection ports (top/bottom/left/right of each node)
|
|
224
|
-
dy = ty - sy
|
|
225
|
-
dx = tx - sx
|
|
226
|
-
|
|
227
|
-
# Choose vertical-first routing (most common for TB layouts)
|
|
228
|
-
if abs(dy) > 10:
|
|
229
|
-
# Connect bottom of src to top of tgt (or top to bottom if reversed)
|
|
230
|
-
if dy > 0:
|
|
231
|
-
# src above tgt
|
|
232
|
-
p1x, p1y = sx, src.y + src.height # bottom of src
|
|
233
|
-
p4x, p4y = tx, tgt.y # top of tgt
|
|
234
|
-
else:
|
|
235
|
-
# src below tgt
|
|
236
|
-
p1x, p1y = sx, src.y # top of src
|
|
237
|
-
p4x, p4y = tx, tgt.y + tgt.height # bottom of tgt
|
|
238
|
-
|
|
239
|
-
# Midpoint Y for the horizontal segment
|
|
240
|
-
mid_y = (p1y + p4y) / 2
|
|
241
|
-
|
|
242
|
-
# Build orthogonal path: vertical → horizontal → vertical
|
|
243
|
-
if abs(p1x - p4x) < 3:
|
|
244
|
-
# Nodes are vertically aligned, straight line
|
|
245
|
-
points = f"{p1x:.1f},{p1y:.1f} {p4x:.1f},{p4y:.1f}"
|
|
246
|
-
else:
|
|
247
|
-
points = f"{p1x:.1f},{p1y:.1f} {p1x:.1f},{mid_y:.1f} {p4x:.1f},{mid_y:.1f} {p4x:.1f},{p4y:.1f}"
|
|
248
|
-
else:
|
|
249
|
-
# Horizontal connection (same layer)
|
|
250
|
-
if dx > 0:
|
|
251
|
-
p1x, p1y = src.x + src.width, sy # right of src
|
|
252
|
-
p4x, p4y = tgt.x, ty # left of tgt
|
|
253
|
-
else:
|
|
254
|
-
p1x, p1y = src.x, sy # left of src
|
|
255
|
-
p4x, p4y = tgt.x + tgt.width, ty # right of tgt
|
|
256
|
-
|
|
257
|
-
if abs(p1y - p4y) < 3:
|
|
258
|
-
points = f"{p1x:.1f},{p1y:.1f} {p4x:.1f},{p4y:.1f}"
|
|
259
|
-
else:
|
|
260
|
-
mid_x = (p1x + p4x) / 2
|
|
261
|
-
points = f"{p1x:.1f},{p1y:.1f} {mid_x:.1f},{p1y:.1f} {mid_x:.1f},{p4y:.1f} {p4x:.1f},{p4y:.1f}"
|
|
262
|
-
|
|
263
|
-
# Arrow head (small triangle at end point)
|
|
264
|
-
has_arrow = edge.style.get("endArrow", "classic") != "none"
|
|
265
|
-
arrow_svg = ""
|
|
266
|
-
if has_arrow:
|
|
267
|
-
# Parse last two points to determine arrow direction
|
|
268
|
-
pts = points.strip().split()
|
|
269
|
-
if len(pts) >= 2:
|
|
270
|
-
last = pts[-1].split(",")
|
|
271
|
-
prev = pts[-2].split(",")
|
|
272
|
-
lx, ly = float(last[0]), float(last[1])
|
|
273
|
-
px, py = float(prev[0]), float(prev[1])
|
|
274
|
-
adx, ady = lx - px, ly - py
|
|
275
|
-
length = max((adx**2 + ady**2)**0.5, 0.001)
|
|
276
|
-
# Normalize
|
|
277
|
-
ux, uy = adx/length, ady/length
|
|
278
|
-
# Arrow triangle (size 8)
|
|
279
|
-
sz = 8
|
|
280
|
-
# Perpendicular
|
|
281
|
-
rx, ry = -uy * sz * 0.5, ux * sz * 0.5
|
|
282
|
-
# Arrow base point
|
|
283
|
-
bx, by = lx - ux * sz, ly - uy * sz
|
|
284
|
-
arrow_svg = (f' <polygon points="{lx:.1f},{ly:.1f} {bx+rx:.1f},{by+ry:.1f} '
|
|
285
|
-
f'{bx-rx:.1f},{by-ry:.1f}" fill="{stroke}" />')
|
|
286
|
-
|
|
287
|
-
svg_lines.append(f' <polyline points="{points}" fill="none" '
|
|
288
|
-
f'stroke="{stroke}" stroke-width="1.5"{dash} stroke-linejoin="round" />')
|
|
289
|
-
if arrow_svg:
|
|
290
|
-
svg_lines.append(arrow_svg)
|
|
291
|
-
|
|
292
|
-
# Edge label - position at midpoint of the polyline path
|
|
293
|
-
if edge.label:
|
|
294
|
-
pts = [tuple(map(float, p.split(","))) for p in points.strip().split()]
|
|
295
|
-
if len(pts) >= 2:
|
|
296
|
-
mid_idx = len(pts) // 2
|
|
297
|
-
if len(pts) % 2 == 0:
|
|
298
|
-
lx = (pts[mid_idx-1][0] + pts[mid_idx][0]) / 2
|
|
299
|
-
ly = (pts[mid_idx-1][1] + pts[mid_idx][1]) / 2
|
|
300
|
-
else:
|
|
301
|
-
lx, ly = pts[mid_idx]
|
|
302
|
-
ly -= 8
|
|
303
|
-
label = edge.label.replace("&", "&").replace("<", "<").replace(">", ">")
|
|
304
|
-
svg_lines.append(f' <rect x="{lx-len(label)*3.5-4}" y="{ly-10}" '
|
|
305
|
-
f'width="{len(label)*7+8}" height="16" rx="3" fill="white" fill-opacity="0.85" />')
|
|
306
|
-
svg_lines.append(f' <text x="{lx}" y="{ly}" text-anchor="middle" dominant-baseline="central" '
|
|
307
|
-
f'font-family="Helvetica, Arial, sans-serif" font-size="11" '
|
|
308
|
-
f'fill="{stroke}">{label}</text>')
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
def clip_to_rect(sx, sy, tx, ty, node):
|
|
312
|
-
"""Clip a line from (sx,sy) toward (tx,ty) to the boundary of node's rect."""
|
|
313
|
-
cx = node.x + node.width / 2
|
|
314
|
-
cy = node.y + node.height / 2
|
|
315
|
-
dx = tx - sx
|
|
316
|
-
dy = ty - sy
|
|
317
|
-
if abs(dx) < 0.001 and abs(dy) < 0.001:
|
|
318
|
-
return sx, sy
|
|
319
|
-
|
|
320
|
-
hw = node.width / 2
|
|
321
|
-
hh = node.height / 2
|
|
322
|
-
|
|
323
|
-
# Find intersection with rect boundary
|
|
324
|
-
t_vals = []
|
|
325
|
-
if abs(dx) > 0.001:
|
|
326
|
-
t_vals.append(hw / abs(dx))
|
|
327
|
-
if abs(dy) > 0.001:
|
|
328
|
-
t_vals.append(hh / abs(dy))
|
|
329
|
-
if t_vals:
|
|
330
|
-
t = min(t_vals)
|
|
331
|
-
return cx + dx * t * (1 if dx > 0 else -1) / max(abs(dx), 0.001) * min(hw, abs(dx) * t), \
|
|
332
|
-
cy + dy * t * (1 if dy > 0 else -1) / max(abs(dy), 0.001) * min(hh, abs(dy) * t)
|
|
333
|
-
return sx, sy
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
def clip_to_rect(sx, sy, tx, ty, node: NodeInfo):
|
|
337
|
-
"""Clip point (sx, sy) to boundary of node rect, coming from direction of (tx, ty)."""
|
|
338
|
-
cx = node.x + node.width / 2
|
|
339
|
-
cy = node.y + node.height / 2
|
|
340
|
-
dx = tx - cx
|
|
341
|
-
dy = ty - cy
|
|
342
|
-
|
|
343
|
-
if abs(dx) < 0.01 and abs(dy) < 0.01:
|
|
344
|
-
return sx, sy
|
|
345
|
-
|
|
346
|
-
hw = node.width / 2
|
|
347
|
-
hh = node.height / 2
|
|
348
|
-
|
|
349
|
-
# Parametric intersection
|
|
350
|
-
scale_x = abs(dx / hw) if hw > 0 else 999
|
|
351
|
-
scale_y = abs(dy / hh) if hh > 0 else 999
|
|
352
|
-
scale = max(scale_x, scale_y)
|
|
353
|
-
|
|
354
|
-
if scale < 0.01:
|
|
355
|
-
return sx, sy
|
|
356
|
-
|
|
357
|
-
return cx + dx / scale, cy + dy / scale
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
def render_svg(nodes: dict, edges: list, groups: dict,
|
|
361
|
-
width: int = 1280, height: int = 720,
|
|
362
|
-
title: str = "", bg: str = "#ffffff",
|
|
363
|
-
padding: int = 40) -> str:
|
|
364
|
-
"""Render parsed drawio data as SVG string."""
|
|
365
|
-
|
|
366
|
-
# Auto-scale to fit canvas
|
|
367
|
-
if nodes:
|
|
368
|
-
all_items = list(nodes.values()) + list(groups.values())
|
|
369
|
-
min_x = min(n.x for n in all_items)
|
|
370
|
-
min_y = min(n.y for n in all_items)
|
|
371
|
-
max_x = max(n.x + n.width for n in all_items)
|
|
372
|
-
max_y = max(n.y + n.height for n in all_items)
|
|
373
|
-
|
|
374
|
-
content_w = max_x - min_x
|
|
375
|
-
content_h = max_y - min_y
|
|
376
|
-
avail_w = width - 2 * padding
|
|
377
|
-
avail_h = height - 2 * padding - (40 if title else 0)
|
|
378
|
-
|
|
379
|
-
scale = min(avail_w / max(content_w, 1), avail_h / max(content_h, 1), 2.0)
|
|
380
|
-
|
|
381
|
-
offset_x = padding + (avail_w - content_w * scale) / 2 - min_x * scale
|
|
382
|
-
offset_y = padding + (40 if title else 0) + (avail_h - content_h * scale) / 2 - min_y * scale
|
|
383
|
-
|
|
384
|
-
# Apply transform
|
|
385
|
-
for n in nodes.values():
|
|
386
|
-
n.x = n.x * scale + offset_x
|
|
387
|
-
n.y = n.y * scale + offset_y
|
|
388
|
-
n.width *= scale
|
|
389
|
-
n.height *= scale
|
|
390
|
-
for g in groups.values():
|
|
391
|
-
g.x = g.x * scale + offset_x
|
|
392
|
-
g.y = g.y * scale + offset_y
|
|
393
|
-
g.width *= scale
|
|
394
|
-
g.height *= scale
|
|
395
|
-
|
|
396
|
-
lines = [
|
|
397
|
-
f'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 {width} {height}" width="{width}" height="{height}">',
|
|
398
|
-
f' <rect width="{width}" height="{height}" fill="{bg}" />',
|
|
399
|
-
]
|
|
400
|
-
|
|
401
|
-
# Title
|
|
402
|
-
if title:
|
|
403
|
-
lines.append(f' <text x="{width/2}" y="32" text-anchor="middle" '
|
|
404
|
-
f'font-family="Helvetica, Arial, sans-serif" font-size="20" '
|
|
405
|
-
f'font-weight="bold" fill="#333333">{title}</text>')
|
|
406
|
-
|
|
407
|
-
# Groups (background)
|
|
408
|
-
for g in groups.values():
|
|
409
|
-
r = 8
|
|
410
|
-
fill = color_from_style(g.style, "fillColor", "#f5f5f5")
|
|
411
|
-
stroke = color_from_style(g.style, "strokeColor", "#999999")
|
|
412
|
-
lines.append(f' <rect x="{g.x}" y="{g.y}" width="{g.width}" height="{g.height}" '
|
|
413
|
-
f'rx="{r}" fill="{fill}" stroke="{stroke}" stroke-width="1" '
|
|
414
|
-
f'stroke-dasharray="4 4" />')
|
|
415
|
-
if g.label:
|
|
416
|
-
label = g.label.replace("&", "&").replace("<", "<")
|
|
417
|
-
lines.append(f' <text x="{g.x + 10}" y="{g.y + 18}" '
|
|
418
|
-
f'font-family="Helvetica, Arial, sans-serif" font-size="13" '
|
|
419
|
-
f'font-weight="bold" fill="#666666">{label}</text>')
|
|
420
|
-
|
|
421
|
-
# Edges (behind nodes)
|
|
422
|
-
for e in edges:
|
|
423
|
-
svg_edge(e, nodes, lines)
|
|
424
|
-
|
|
425
|
-
# Nodes (on top)
|
|
426
|
-
for n in nodes.values():
|
|
427
|
-
svg_shape(n, lines)
|
|
428
|
-
|
|
429
|
-
lines.append('</svg>')
|
|
430
|
-
return "\n".join(lines)
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
def main():
|
|
434
|
-
parser = argparse.ArgumentParser(description="Convert draw.io to PPT-compatible SVG")
|
|
435
|
-
parser.add_argument("input", help="Input .drawio file")
|
|
436
|
-
parser.add_argument("-o", "--output", required=True, help="Output .svg file")
|
|
437
|
-
parser.add_argument("--width", type=int, default=1280, help="SVG width (default: 1280)")
|
|
438
|
-
parser.add_argument("--height", type=int, default=720, help="SVG height (default: 720)")
|
|
439
|
-
parser.add_argument("--title", default="", help="Diagram title")
|
|
440
|
-
parser.add_argument("--background", default="#ffffff", help="Background color")
|
|
441
|
-
parser.add_argument("--padding", type=int, default=40, help="Padding around content")
|
|
442
|
-
args = parser.parse_args()
|
|
443
|
-
|
|
444
|
-
nodes, edges, groups = parse_drawio(args.input)
|
|
445
|
-
svg = render_svg(nodes, edges, groups,
|
|
446
|
-
width=args.width, height=args.height,
|
|
447
|
-
title=args.title, bg=args.background,
|
|
448
|
-
padding=args.padding)
|
|
449
|
-
|
|
450
|
-
with open(args.output, "w", encoding="utf-8") as f:
|
|
451
|
-
f.write(svg)
|
|
452
|
-
|
|
453
|
-
print(f"✅ Converted: {args.output}")
|
|
454
|
-
print(f" Canvas: {args.width}x{args.height}, Nodes: {len(nodes)}, Edges: {len(edges)}")
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
if __name__ == "__main__":
|
|
458
|
-
main()
|
|
Binary file
|
package/skills/ppt-master/scripts/image_backends/__pycache__/backend_aigw_gemini.cpython-314.pyc
DELETED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|