├── .github ├── CODEOWNERS ├── FUNDING.yml ├── dependabot.yaml ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md └── workflows │ ├── dockerhub.yaml │ ├── publish.yaml │ ├── linter.yaml │ ├── autoupdate-drawio-exporter.yaml │ └── drawio-export.yaml ├── tests ├── expected │ ├── option-git-ref_HEAD.log │ ├── option-on-changes_no_changes.log │ ├── export-empty.log │ ├── args-path_must_exists.log │ ├── types-xml.log │ ├── types-pdf-all-pages.log │ ├── option-remove-page-suffix.log │ ├── args-path.log │ ├── export-vscode.log │ ├── types-default.log │ ├── types-pdf.log │ ├── types-png.log │ ├── option-on-changes.log │ ├── export-spaces.log │ ├── option-git-ref_root_commit.log │ ├── export-name-collision.log │ ├── option-git-ref_need_git_repo.log │ ├── option-git-ref_must_exists.log │ ├── export-shapes.log │ ├── option-git-ref_need_on-changes.log │ ├── print_help_if_wrong_argument.log │ ├── export-issue-140.log │ ├── types-adoc.log │ ├── export-tree.log │ ├── issue-140-page-index-mismatch-Blue.svg │ ├── issue-140-page-index-mismatch-Green.svg │ ├── issue-140-page-index-mismatch-Yellow.svg │ └── issue-140-page-index-mismatch-Purple.svg ├── .gitconfig ├── data │ ├── empty │ │ └── empty.drawio │ ├── name-collision │ │ ├── name.drawio │ │ └── name-collision.drawio │ ├── single-page │ │ └── single-page.drawio │ ├── tree │ │ ├── file1.drawio │ │ ├── folder1 │ │ │ ├── file2.1.drawio │ │ │ └── file2.2.drawio │ │ └── folder2 │ │ │ └── folder3 │ │ │ └── file3.drawio │ ├── space │ │ └── file with spaces.drawio │ ├── types │ │ └── nominal.drawio │ ├── vscode │ │ └── vscode.drawio │ ├── issue-140 │ │ └── page-index-mismatch.drawio │ └── shapes │ │ └── shapes.drawio ├── types-default.bats ├── types-adoc.bats ├── help.bats ├── types-png.bats ├── option-remove-page-suffix.bats ├── args-path.bats ├── types-xml.bats ├── types-pdf.bats ├── option-on-changes.bats ├── issues.bats ├── export.bats ├── option-git-ref.bats └── base.bats ├── .dockerignore ├── .gitignore ├── src └── runner.sh ├── .editorconfig ├── Dockerfile ├── SECURITY.md ├── LICENSE ├── Makefile ├── DOCKER.md ├── CONTRIBUTING.md ├── README.adoc └── CODE_OF_CONDUCT.md /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @rlespinasse 2 | -------------------------------------------------------------------------------- /tests/expected/option-git-ref_HEAD.log: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /tests/.gitconfig: -------------------------------------------------------------------------------- 1 | [safe] 2 | directory = * 3 | -------------------------------------------------------------------------------- /tests/expected/option-on-changes_no_changes.log: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | export/ 2 | test-*/ 3 | node_modules/ 4 | -------------------------------------------------------------------------------- /tests/data/empty/empty.drawio: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /tests/expected/export-empty.log: -------------------------------------------------------------------------------- 1 | + export file : empty.drawio 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | export/ 2 | test-*/ 3 | node_modules/ 4 | tests/output/ 5 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: rlespinasse 4 | -------------------------------------------------------------------------------- /tests/expected/args-path_must_exists.log: -------------------------------------------------------------------------------- 1 | Error: path 'unknown-folder' must exist (as directory or file) 2 | -------------------------------------------------------------------------------- /tests/expected/types-xml.log: -------------------------------------------------------------------------------- 1 | + export file : nominal.drawio 2 | - export all pages 3 | \ generate xml file 4 | -------------------------------------------------------------------------------- /tests/expected/types-pdf-all-pages.log: -------------------------------------------------------------------------------- 1 | + export file : nominal.drawio 2 | - export all pages 3 | \ generate pdf file 4 | -------------------------------------------------------------------------------- /src/runner.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | 4 | "${DRAWIO_DESKTOP_EXECUTABLE_PATH:?}" --drawio-desktop-headless "$@" 5 | -------------------------------------------------------------------------------- /tests/expected/option-remove-page-suffix.log: -------------------------------------------------------------------------------- 1 | + export file : single-page.drawio 2 | - export page 1 : Page-1 3 | \ generate pdf file 4 | -------------------------------------------------------------------------------- /tests/expected/args-path.log: -------------------------------------------------------------------------------- 1 | + export file : nominal.drawio 2 | - export page 1 : Page-1 3 | \ generate pdf file 4 | - export page 2 : Page-2 5 | \ generate pdf file 6 | -------------------------------------------------------------------------------- /tests/expected/export-vscode.log: -------------------------------------------------------------------------------- 1 | + export file : vscode.drawio 2 | - export page 1 : Page-1 3 | \ generate pdf file 4 | - export page 2 : Page-2 5 | \ generate pdf file 6 | -------------------------------------------------------------------------------- /tests/expected/types-default.log: -------------------------------------------------------------------------------- 1 | + export file : nominal.drawio 2 | - export page 1 : Page-1 3 | \ generate pdf file 4 | - export page 2 : Page-2 5 | \ generate pdf file 6 | -------------------------------------------------------------------------------- /tests/expected/types-pdf.log: -------------------------------------------------------------------------------- 1 | + export file : nominal.drawio 2 | - export page 1 : Page-1 3 | \ generate pdf file 4 | - export page 2 : Page-2 5 | \ generate pdf file 6 | -------------------------------------------------------------------------------- /tests/expected/types-png.log: -------------------------------------------------------------------------------- 1 | + export file : nominal.drawio 2 | - export page 1 : Page-1 3 | \ generate png file 4 | - export page 2 : Page-2 5 | \ generate png file 6 | -------------------------------------------------------------------------------- /tests/expected/option-on-changes.log: -------------------------------------------------------------------------------- 1 | + export file : nominal.drawio 2 | - export page 1 : Page-1 3 | \ generate pdf file 4 | - export page 2 : Page-2 5 | \ generate pdf file 6 | -------------------------------------------------------------------------------- /tests/expected/export-spaces.log: -------------------------------------------------------------------------------- 1 | + export file : file with spaces.drawio 2 | - export page 1 : Page-1 3 | \ generate pdf file 4 | - export page 2 : Page-2 5 | \ generate pdf file 6 | -------------------------------------------------------------------------------- /tests/expected/option-git-ref_root_commit.log: -------------------------------------------------------------------------------- 1 | + export file : nominal.drawio 2 | - export page 1 : Page-1 3 | \ generate pdf file 4 | - export page 2 : Page-2 5 | \ generate pdf file 6 | -------------------------------------------------------------------------------- /tests/types-default.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | . tests/base.bats 4 | 5 | @test "Export using default configuration" { 6 | docker_test "" 0 "types-default" "tests/data/types" 7 | } 8 | -------------------------------------------------------------------------------- /tests/types-adoc.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | . tests/base.bats 4 | 5 | @test "Export as adoc" { 6 | docker_test "" 0 "types-adoc" "tests/data/types" -f adoc -t -o test-assets-adoc 7 | } 8 | 9 | -------------------------------------------------------------------------------- /tests/help.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | . tests/base.bats 4 | 5 | @test "Print help when using wrong argument" { 6 | docker_test "" 1 "print_help_if_wrong_argument" "tests/data" --wrong-argument 7 | } 8 | -------------------------------------------------------------------------------- /tests/types-png.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | . tests/base.bats 4 | 5 | @test "Export as png using short options" { 6 | docker_test "" 0 "types-png" "tests/data/types" -f png -t -o test-assets-png 7 | } 8 | -------------------------------------------------------------------------------- /tests/expected/export-name-collision.log: -------------------------------------------------------------------------------- 1 | + export file : name-collision.drawio 2 | - export page 1 : Page-1 3 | \ generate pdf file 4 | + export file : name.drawio 5 | - export page 1 : Page-1 6 | \ generate pdf file 7 | -------------------------------------------------------------------------------- /tests/expected/option-git-ref_need_git_repo.log: -------------------------------------------------------------------------------- 1 | Error: can't explore path . 2 | 3 | Caused by: 4 | 0: need to be a git repository . 5 | 1: could not find repository at '.'; class=Repository (6); code=NotFound (-3) 6 | -------------------------------------------------------------------------------- /tests/expected/option-git-ref_must_exists.log: -------------------------------------------------------------------------------- 1 | Error: can't explore path . 2 | 3 | Caused by: 4 | 0: need to be a git repository . 5 | 1: repository path '/data' is not owned by current user; class=Config (7); code=Owner (-36) 6 | -------------------------------------------------------------------------------- /tests/expected/export-shapes.log: -------------------------------------------------------------------------------- 1 | + export file : shapes.drawio 2 | - export page 1 : AWS 3 | \ generate pdf file 4 | - export page 2 : Azure 5 | \ generate pdf file 6 | - export page 3 : GCP 7 | \ generate pdf file 8 | - export page 4 : K8S 9 | \ generate pdf file 10 | -------------------------------------------------------------------------------- /tests/expected/option-git-ref_need_on-changes.log: -------------------------------------------------------------------------------- 1 | error: the following required arguments were not provided: 2 | --on-changes 3 | 4 | Usage: drawio-exporter --on-changes --drawio-desktop-headless --git-ref [PATH] 5 | 6 | For more information, try '--help'. 7 | -------------------------------------------------------------------------------- /tests/option-remove-page-suffix.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | . tests/base.bats 4 | 5 | @test "Export using --remove-page-suffix" { 6 | docker_test "" 0 "option-remove-page-suffix" "tests/data/single-page" --remove-page-suffix --output test-assets-remove-page-suffix 7 | } 8 | -------------------------------------------------------------------------------- /tests/expected/print_help_if_wrong_argument.log: -------------------------------------------------------------------------------- 1 | error: unexpected argument '--wrong-argument' found 2 | 3 | tip: to pass '--wrong-argument' as a value, use '-- --wrong-argument' 4 | 5 | Usage: drawio-exporter --drawio-desktop-headless [PATH] 6 | 7 | For more information, try '--help'. 8 | -------------------------------------------------------------------------------- /tests/expected/export-issue-140.log: -------------------------------------------------------------------------------- 1 | + export file : page-index-mismatch.drawio 2 | - export page 1 : Blue 3 | \ generate svg file 4 | - export page 2 : Green 5 | \ generate svg file 6 | - export page 3 : Purple 7 | \ generate svg file 8 | - export page 4 : Yellow 9 | \ generate svg file 10 | -------------------------------------------------------------------------------- /tests/args-path.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | . tests/base.bats 4 | 5 | @test "Argument PATH must exists" { 6 | docker_test "" 1 "args-path_must_exists" "tests/data" "unknown-folder" 7 | } 8 | 9 | @test "Export using specific PATH" { 10 | docker_test "" 0 "args-path" "tests/data" "types" 11 | } 12 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # top-most EditorConfig file 2 | root = true 3 | 4 | # Unix-style newlines with a newline ending every file 5 | [*] 6 | charset = utf-8 7 | indent_style = space 8 | indent_size = 2 9 | end_of_line = lf 10 | insert_final_newline = true 11 | trim_trailing_whitespace = true 12 | 13 | [Makefile] 14 | indent_style = tab 15 | indent_size = 4 16 | -------------------------------------------------------------------------------- /tests/types-xml.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | . tests/base.bats 4 | 5 | @test "Export as xml using short options" { 6 | docker_test "" 0 "types-xml" "tests/data/types" -f xml -u -o test-assets-xml 7 | } 8 | 9 | @test "Export as xml using long options" { 10 | docker_test "" 0 "types-xml" "tests/data/types" -f xml --uncompressed -o test-assets-xml 11 | } 12 | -------------------------------------------------------------------------------- /tests/types-pdf.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | . tests/base.bats 4 | 5 | @test "Export as pdf using long options" { 6 | docker_test "" 0 "types-pdf" "tests/data/types" --format pdf --crop --output test-assets-pdf 7 | } 8 | 9 | @test "Export as pdf using all-pages option" { 10 | docker_test "" 0 "types-pdf-all-pages" "tests/data/types" --format pdf --all-pages --output test-assets-pdf 11 | } 12 | -------------------------------------------------------------------------------- /.github/dependabot.yaml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: 'docker' 4 | directory: '/' 5 | commit-message: 6 | prefix: 'feat: ' 7 | schedule: 8 | interval: 'daily' 9 | labels: [] 10 | 11 | - package-ecosystem: 'github-actions' 12 | directory: '/' 13 | schedule: 14 | interval: 'weekly' 15 | groups: 16 | dependencies: 17 | patterns: 18 | - '*' 19 | labels: [] 20 | -------------------------------------------------------------------------------- /tests/expected/types-adoc.log: -------------------------------------------------------------------------------- 1 | + export file : nominal.drawio 2 | - export page 1 : Page-1 3 | \ generate png file 4 | \ generate adoc file 5 | \ include links in adoc file 6 | link 'Some text' to https://github.com/rlespinasse/qanda 7 | link 'Some link' to https://github.com/rlespinasse/qanda 8 | - export page 2 : Page-2 9 | \ generate png file 10 | \ generate adoc file 11 | \ include links in adoc file 12 | link 'Some text' to https://github.com/rlespinasse/qanda 13 | link 'Some link' to https://github.com/rlespinasse/qanda 14 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior 15 | 16 | **Expected behavior** 17 | A clear and concise description of what you expected to happen. 18 | 19 | **Screenshots** 20 | If applicable, add screenshots to help explain your problem. 21 | 22 | **Additional context** 23 | Add any other context about the problem here. 24 | -------------------------------------------------------------------------------- /tests/expected/export-tree.log: -------------------------------------------------------------------------------- 1 | + export file : file1.drawio 2 | - export page 1 : Page-1 3 | \ generate pdf file 4 | - export page 2 : Page-2 5 | \ generate pdf file 6 | + export file : folder1/file2.1.drawio 7 | - export page 1 : Page-1 8 | \ generate pdf file 9 | - export page 2 : Page-2 10 | \ generate pdf file 11 | + export file : folder1/file2.2.drawio 12 | - export page 1 : Page-1 13 | \ generate pdf file 14 | - export page 2 : Page-2 15 | \ generate pdf file 16 | + export file : folder2/folder3/file3.drawio 17 | - export page 1 : Page-1 18 | \ generate pdf file 19 | - export page 2 : Page-2 20 | \ generate pdf file 21 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | #checkov:skip=CKV_DOCKER_2 2 | #checkov:skip=CKV_DOCKER_3 3 | FROM rust:trixie as drawio-exporter-installer 4 | 5 | RUN cargo install drawio-exporter --version 1.4.0 6 | 7 | FROM rlespinasse/drawio-desktop-headless:v1.49.0 8 | 9 | WORKDIR /opt/drawio-exporter 10 | COPY --from=drawio-exporter-installer /usr/local/cargo/bin/drawio-exporter . 11 | COPY src/* ./ 12 | 13 | # disable timeout capabilities since it's a batch 14 | ENV DRAWIO_DESKTOP_COMMAND_TIMEOUT 0 15 | ENV DRAWIO_DESKTOP_RUNNER_COMMAND_LINE "/opt/drawio-exporter/runner.sh" 16 | ENV DRAWIO_DESKTOP_EXECUTABLE_PATH /opt/drawio-exporter/drawio-exporter 17 | 18 | WORKDIR /data 19 | CMD [ "" ] 20 | -------------------------------------------------------------------------------- /.github/workflows/dockerhub.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Update Docker Hub information 3 | 4 | on: 5 | release: 6 | types: [published] 7 | push: 8 | branches: 9 | - v4.x 10 | paths: 11 | - DOCKER.md 12 | - .github/workflows/dockerhub.yaml 13 | 14 | permissions: read-all 15 | 16 | jobs: 17 | dockerHubDescription: 18 | runs-on: ubuntu-latest 19 | 20 | steps: 21 | - uses: actions/checkout@v6 22 | 23 | - name: Sync information on Docker Hub 24 | uses: peter-evans/dockerhub-description@v5 25 | with: 26 | username: rlespinasse 27 | password: ${{ secrets.DOCKER_PASSWORD }} 28 | readme-filepath: ./DOCKER.md 29 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: enhancement 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /tests/option-on-changes.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | . tests/base.bats 4 | 5 | @test "Export using --on-changes" { 6 | # Setup exported files 2 hours before drawio file 7 | docker_test "" 0 "dev_null" "tests/data/types" --output test-assets-dev_null 8 | cp -r tests/data/types/test-assets-dev_null tests/data/types/test-assets-on-changes # To support GitHub Action context 9 | find tests/data/types/test-assets-on-changes -exec touch -d "2 hours ago" -r tests/data/types/nominal.drawio {} + 10 | 11 | # Tests 12 | docker_test "" 0 "option-on-changes" "tests/data/types" --on-changes --output test-assets-on-changes 13 | docker_test "" 0 "option-on-changes_no_changes" "tests/data/types" --on-changes --output test-assets-on-changes 14 | } 15 | -------------------------------------------------------------------------------- /tests/data/name-collision/name.drawio: -------------------------------------------------------------------------------- 1 | tVRNU8MgEP01OeokodPq0da2zjiO43QcvdKwBiqBCNQk/nqhIR/Y6njQU+DtW5Z9b0mEFkW9Vrikd5IAj9KY1BG6jtI0SeKp/TikaZELFLdArhjxpAHYsA/wYEfbMwI6IBopuWFlCGZSCMhMgGGlZBXSXiQPq5Y4hyNgk2F+jD4xYqjvIp0N+A2wnHaVk+llGylwR/adaIqJrEYQWkZooaQ07aqoF8CdeJ0ubd7qm2h/MQXCnEh41KDutzunSRpzvLW+HEgbWYATEWrTnsCZeG1D1Bin6pU7I13lzND99jyThd0oDrpkAmttk1dvWBDcZnfXeY5RvtNnzex2Rx6qh+Zjt5ycpX2b/fW1aTppldwLAi4/idC8oszApsSZi1Z2mCxGTcF9+LhbL8A7KNvLCPL11mAbNaqxlDocqSbcVoOtSecVHVk69Rj2k5T3Bw9i24XvsNuO5P+NHQcT/tuOyY92HCYi0FwbJV9hIblUFhFSWOb8hXH+BcKc5cJuM+sNWHzuPGH2DV35QMEIcWVOmjyMQfw3PqPQ58tjny9O2Jz+ic3Om/5FH+ij/yJafgI= 2 | -------------------------------------------------------------------------------- /tests/data/single-page/single-page.drawio: -------------------------------------------------------------------------------- 1 | tVRNU8MgEP01OeokodPq0da2zjiO43QcvdKwBiqBCNQk/nqhIR/Y6njQU+DtW5Z9b0mEFkW9Vrikd5IAj9KY1BG6jtI0SeKp/TikaZELFLdArhjxpAHYsA/wYEfbMwI6IBopuWFlCGZSCMhMgGGlZBXSXiQPq5Y4hyNgk2F+jD4xYqjvIp0N+A2wnHaVk+llGylwR/adaIqJrEYQWkZooaQ07aqoF8CdeJ0ubd7qm2h/MQXCnEh41KDutzunSRpzvLW+HEgbWYATEWrTnsCZeG1D1Bin6pU7I13lzND99jyThd0oDrpkAmttk1dvWBDcZnfXeY5RvtNnzex2Rx6qh+Zjt5ycpX2b/fW1aTppldwLAi4/idC8oszApsSZi1Z2mCxGTcF9+LhbL8A7KNvLCPL11mAbNaqxlDocqSbcVoOtSecVHVk69Rj2k5T3Bw9i24XvsNuO5P+NHQcT/tuOyY92HCYi0FwbJV9hIblUFhFSWOb8hXH+BcKc5cJuM+sNWHzuPGH2DV35QMEIcWVOmjyMQfw3PqPQ58tjny9O2Jz+ic3Om/5FH+ij/yJafgI= 2 | -------------------------------------------------------------------------------- /tests/data/name-collision/name-collision.drawio: -------------------------------------------------------------------------------- 1 | tVRNU8MgEP01OeokodPq0da2zjiO43QcvdKwBiqBCNQk/nqhIR/Y6njQU+DtW5Z9b0mEFkW9Vrikd5IAj9KY1BG6jtI0SeKp/TikaZELFLdArhjxpAHYsA/wYEfbMwI6IBopuWFlCGZSCMhMgGGlZBXSXiQPq5Y4hyNgk2F+jD4xYqjvIp0N+A2wnHaVk+llGylwR/adaIqJrEYQWkZooaQ07aqoF8CdeJ0ubd7qm2h/MQXCnEh41KDutzunSRpzvLW+HEgbWYATEWrTnsCZeG1D1Bin6pU7I13lzND99jyThd0oDrpkAmttk1dvWBDcZnfXeY5RvtNnzex2Rx6qh+Zjt5ycpX2b/fW1aTppldwLAi4/idC8oszApsSZi1Z2mCxGTcF9+LhbL8A7KNvLCPL11mAbNaqxlDocqSbcVoOtSecVHVk69Rj2k5T3Bw9i24XvsNuO5P+NHQcT/tuOyY92HCYi0FwbJV9hIblUFhFSWOb8hXH+BcKc5cJuM+sNWHzuPGH2DV35QMEIcWVOmjyMQfw3PqPQ58tjny9O2Jz+ic3Om/5FH+ij/yJafgI= 2 | -------------------------------------------------------------------------------- /tests/issues.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | . tests/base.bats 4 | 5 | @test "Issue 140 : page index mismatch" { 6 | docker_test "" 0 "export-issue-140" "tests/data" -f svg issue-140 7 | diff <(xmllint --format tests/expected/issue-140-page-index-mismatch-Blue.svg) <(xmllint --format tests/data/issue-140/export/page-index-mismatch-Blue.svg) 8 | diff <(xmllint --format tests/expected/issue-140-page-index-mismatch-Green.svg) <(xmllint --format tests/data/issue-140/export/page-index-mismatch-Green.svg) 9 | diff <(xmllint --format tests/expected/issue-140-page-index-mismatch-Purple.svg) <(xmllint --format tests/data/issue-140/export/page-index-mismatch-Purple.svg) 10 | diff <(xmllint --format tests/expected/issue-140-page-index-mismatch-Yellow.svg) <(xmllint --format tests/data/issue-140/export/page-index-mismatch-Yellow.svg) 11 | } 12 | -------------------------------------------------------------------------------- /tests/export.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | . tests/base.bats 4 | 5 | @test "Export files with a name collision" { 6 | docker_test "" 0 "export-name-collision" "tests/data/name-collision" 7 | # both files must exists 8 | [ -f "tests/data/name-collision/export/name-Page-1.pdf" ] 9 | [ -f "tests/data/name-collision/export/name-collision-Page-1.pdf" ] 10 | } 11 | 12 | @test "Export files from a folders tree" { 13 | docker_test "" 0 "export-tree" "tests/data/tree" 14 | } 15 | 16 | @test "Export file with spaces" { 17 | docker_test "" 0 "export-spaces" "tests/data/space" 18 | } 19 | 20 | @test "Export file using shapes" { 21 | docker_test "" 0 "export-shapes" "tests/data/shapes" 22 | } 23 | 24 | @test "Export file without any diagrams" { 25 | docker_test "" 0 "export-empty" "tests/data/empty" 26 | } 27 | 28 | @test "Export file from vscode" { 29 | docker_test "" 0 "export-vscode" "tests/data/vscode" 30 | } 31 | -------------------------------------------------------------------------------- /.github/workflows/publish.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Publish to Registry 3 | 4 | on: 5 | release: 6 | types: [published, edited] 7 | 8 | permissions: read-all 9 | 10 | jobs: 11 | update: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v6 15 | 16 | - uses: rlespinasse/github-slug-action@v5 17 | 18 | - name: Set up QEMU 19 | uses: docker/setup-qemu-action@v3 20 | with: 21 | platforms: "arm64,arm" 22 | 23 | - name: Set up Docker Buildx 24 | uses: docker/setup-buildx-action@v3 25 | 26 | - name: Publish to Registry 27 | uses: elgohr/Publish-Docker-Github-Action@v5 28 | with: 29 | name: ${{ github.repository }} 30 | username: ${{ secrets.DOCKER_USERNAME }} 31 | password: ${{ secrets.DOCKER_PASSWORD }} 32 | tags: "latest,${{ env.GITHUB_REF_SLUG }}" 33 | platforms: linux/amd64,linux/arm64 34 | -------------------------------------------------------------------------------- /.github/workflows/linter.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Lint Code Base 3 | 4 | on: pull_request 5 | 6 | permissions: read-all 7 | 8 | jobs: 9 | lint: 10 | runs-on: ubuntu-latest 11 | 12 | permissions: 13 | contents: read 14 | packages: read 15 | statuses: write 16 | 17 | steps: 18 | - name: Checkout Code 19 | uses: actions/checkout@v6 20 | with: 21 | # Full git history is needed to get a proper 22 | # list of changed files within `super-linter` 23 | fetch-depth: 0 24 | 25 | - name: Lint Code Base 26 | uses: super-linter/super-linter@v8 27 | env: 28 | VALIDATE_ALL_CODEBASE: false 29 | VALIDATE_BIOME_FORMAT: false 30 | VALIDATE_BIOME_LINT: false 31 | VALIDATE_GITHUB_ACTIONS_ZIZMOR: false 32 | VALIDATE_TRIVY: false 33 | VALIDATE_YAML_PRETTIER: false 34 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 35 | -------------------------------------------------------------------------------- /.github/workflows/autoupdate-drawio-exporter.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Autoupdate Drawio Exporter 3 | 4 | on: 5 | schedule: 6 | - cron: "0 0 * * 1" # Every Monday at midnight (UTC) 7 | workflow_dispatch: 8 | 9 | permissions: 10 | contents: write 11 | pull-requests: write 12 | 13 | concurrency: 14 | group: autoupdate-drawio-exporter 15 | cancel-in-progress: true 16 | 17 | jobs: 18 | autoupdate: 19 | runs-on: ubuntu-latest 20 | steps: 21 | - uses: actions/checkout@v6 22 | 23 | - run: make autoupdate-drawio-exporter 24 | id: autoupdate-drawio-exporter 25 | env: 26 | GH_TOKEN: ${{ secrets.GH_TOKEN }} 27 | shell: bash 28 | 29 | - uses: peter-evans/create-pull-request@v7 30 | with: 31 | title: "feat: update to drawio-exporter ${{ steps.autoupdate-drawio-exporter.outputs.release_version }}" 32 | branch: autoupdate-drawio-exporter 33 | token: ${{ secrets.GH_TOKEN }} 34 | -------------------------------------------------------------------------------- /tests/expected/issue-140-page-index-mismatch-Blue.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /tests/expected/issue-140-page-index-mismatch-Green.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /tests/expected/issue-140-page-index-mismatch-Yellow.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /tests/expected/issue-140-page-index-mismatch-Purple.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions and Branches 4 | 5 | | Version | Supported | End of Support | Branch | 6 | | ------- | ------------------ | -------------- | ------ | 7 | | 4.x | :white_check_mark: | | v4.x | 8 | | 3.x | :x: | 2021-03-29 | | 9 | | 2.x | :x: | 2020-06-30 | | 10 | | 1.x | :x: | 2020-05-02 | | 11 | 12 | ### End of Life of a branch 13 | 14 | Since `2024-10-27`, when a new major version is released, 15 | 16 | - The previous one will continue to receive security patches for 3 months, 17 | - After the 3 months, the branch is deleted, and only the tags remain. 18 | 19 | ## Reporting a Vulnerability 20 | 21 | In this project, you can report a Vulnerability by creating a [draft security advisory](https://github.com/rlespinasse/drawio-export/security/advisories). 22 | 23 | If the vulnerability is confirmed, a fix will be produced and the advisory will be published. 24 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Romain Lespinasse 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /tests/option-git-ref.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | . tests/base.bats 4 | 5 | @test "Option --git-ref need a git repository" { 6 | docker_test "" 1 "option-git-ref_need_git_repo" "tests/data" --on-changes --git-ref HEAD 7 | } 8 | 9 | @test "Option --git-ref need to be a valid Git reference" { 10 | docker_test "" 1 "option-git-ref_must_exists" "." --on-changes --git-ref unknown-ref 11 | } 12 | 13 | @test "Option --git-ref need option --on-changes" { 14 | docker_test "" 1 "option-git-ref_need_on-changes" "." --git-ref HEAD 15 | } 16 | 17 | @test "Export using --git-ref (has changes)" { 18 | docker_test "-v $(pwd)/tests/.gitconfig:/root/.gitconfig:ro" 0 "option-git-ref_root_commit" "." --on-changes --git-ref $(git rev-list HEAD | tail -n 1) --output test-assets-git-ref "tests/data/types" 19 | } 20 | 21 | @test "Export using --git-ref HEAD (no changes)" { 22 | if [ -n "$(git diff --name-only --cached)" ]; then 23 | skip "This test is designed to work without any files in the commit staging area" 24 | fi 25 | 26 | docker_test "-v $(pwd)/tests/.gitconfig:/root/.gitconfig:ro" 0 "option-git-ref_HEAD" "." --on-changes --git-ref HEAD --output test-assets-git-ref "tests/data/types" 27 | } 28 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: build build-no-cache build-multiarch cleanup run test test-ci-setup test-ci 2 | 3 | DOCKER_IMAGE?=rlespinasse/drawio-export:local 4 | build: 5 | @docker build -t ${DOCKER_IMAGE} . 6 | 7 | build-no-cache: 8 | @docker build --no-cache --progress plain -t ${DOCKER_IMAGE} . 9 | 10 | build-multiarch: 11 | @docker buildx build --platform linux/amd64,linux/arm64 -t ${DOCKER_IMAGE} . 12 | 13 | cleanup: 14 | @rm -rf tests/output 15 | @find tests -name "export" | xargs -I {} rm -r "{}" 16 | @find tests -name "test-*" | xargs -I {} rm -r "{}" 17 | 18 | RUN_ARGS?= 19 | DOCKER_OPTIONS?= 20 | run: 21 | @docker run -t $(DOCKER_OPTIONS) -w /data -v $(PWD):/data ${DOCKER_IMAGE} ${RUN_ARGS} 22 | 23 | test: cleanup build test-ci 24 | 25 | test-ci-setup: 26 | @npm install bats 27 | @sudo apt-get update 28 | @sudo apt-get install -y libxml2-utils 29 | 30 | test-ci: 31 | @mkdir -p tests/output 32 | @DOCKER_IMAGE=$(DOCKER_IMAGE) npx bats --verbose-run -r tests 33 | 34 | autoupdate-drawio-exporter: 35 | @$(eval DRAWIO_EXPORTER_RELEASE := $(shell gh release list --repo rlespinasse/drawio-exporter | grep "Latest" | cut -f1 | sed 's/^v//')) 36 | @sed -i "s/version.*/version $(DRAWIO_EXPORTER_RELEASE)/" Dockerfile 37 | @test -z "${GITHUB_OUTPUT}" || echo "release_version=$(DRAWIO_DESKTOP_RELEASE)" >> "${GITHUB_OUTPUT}" 38 | -------------------------------------------------------------------------------- /tests/base.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | docker_test() { 4 | local docker_opts="$1" 5 | local status=$2 6 | local output_file=$3 7 | local data_folder=$4 8 | shift 4 9 | 10 | # shellcheck disable=SC2086,SC2046 11 | echo docker container run -t $docker_opts -w /data -v $(pwd)/${data_folder:-}:/data ${DOCKER_IMAGE} "$@" >>tests/output/$output_file-command.log 12 | # shellcheck disable=SC2086,SC2046 13 | run docker container run -t $docker_opts -w /data -v $(pwd)/${data_folder:-}:/data ${DOCKER_IMAGE} "$@" 14 | 15 | # shellcheck disable=SC2154 16 | echo "$output" | tee "tests/output/$output_file.log" | sed 's#\[.*:.*/.*\..*:.*:.*\(.*\)\] ##' >"tests/output/$output_file-comp.log" 17 | 18 | # Test status 19 | # shellcheck disable=SC2086 20 | [ "$status" -eq $status ] 21 | 22 | # Test output 23 | if [ -f "tests/expected/$output_file.log" ]; then 24 | diff -u --strip-trailing-cr "tests/expected/$output_file.log" "tests/output/$output_file-comp.log" >"tests/output/$output_file-diff.log" 25 | elif [ -f "tests/expected/uniq-$output_file.log" ]; then 26 | diff -u --strip-trailing-cr "tests/expected/uniq-$output_file.log" <(sort -u "tests/output/$output_file-comp.log") >"tests/output/$output_file-diff.log" 27 | fi 28 | if [ -f "tests/output/$output_file-diff.log" ]; then 29 | [ "$(cat "tests/output/$output_file-diff.log")" = "" ] 30 | fi 31 | } 32 | -------------------------------------------------------------------------------- /DOCKER.md: -------------------------------------------------------------------------------- 1 | # Draw.io Export 2 | 3 | Export Draw.io diagrams using docker 4 | 5 | ## Features 6 | 7 | * Recursive export 8 | * Partial export (newer, or based on git reference) 9 | * Additional export formats with link extraction 10 | 11 | ## Supported Export formats 12 | 13 | * **draw.io** export formats : jpg, pdf, png, svg, vsdx, and xml 14 | * **drawio-exporter** additional formats 15 | * adoc - Export in PNG and create an additional Asciidoc file (with support external links). 16 | * md - Export in PNG and create an additional Markdown file (with support external links). 17 | 18 | ## Installation 19 | 20 | ```bash 21 | docker pull rlespinasse/drawio-export 22 | ``` 23 | 24 | See [Dockerfile][2] 25 | 26 | ## Usage 27 | 28 | Print the available options 29 | 30 | ```bash 31 | docker run -it rlespinasse/drawio-export --help 32 | ``` 33 | 34 | Simple run with default options 35 | 36 | ```bash 37 | $ cd directory-with-drawio-files 38 | $ docker run -it -v $(pwd):/data rlespinasse/drawio-export 39 | + export file : ./file1.drawio 40 | - export page 1 : Page-1 41 | \ generate pdf file 42 | - export page 2 : Page-2 43 | \ generate pdf file 44 | ``` 45 | 46 | Want to read more, go to [rlespinasse/drawio-export][1] on GitHub. 47 | 48 | [1]: https://github.com/rlespinasse/drawio-export 49 | [2]: https://github.com/rlespinasse/drawio-export/blob/master/Dockerfile 50 | -------------------------------------------------------------------------------- /tests/data/tree/file1.drawio: -------------------------------------------------------------------------------- 1 | tVRNU8MgEP01OeokodPq0da2zjiO43QcvdKwBiqBCNQk/nqhIR/Y6njQU+DtW5Z9b0mEFkW9Vrikd5IAj9KY1BG6jtI0SeKp/TikaZELFLdArhjxpAHYsA/wYEfbMwI6IBopuWFlCGZSCMhMgGGlZBXSXiQPq5Y4hyNgk2F+jD4xYqjvIp0N+A2wnHaVk+llGylwR/adaIqJrEYQWkZooaQ07aqoF8CdeJ0ubd7qm2h/MQXCnEh41KDutzunSRpzvLW+HEgbWYATEWrTnsCZeG1D1Bin6pU7I13lzND99jyThd0oDrpkAmttk1dvWBDcZnfXeY5RvtNnzex2Rx6qh+Zjt5ycpX2b/fW1aTppldwLAi4/idC8oszApsSZi1Z2mCxGTcF9+LhbL8A7KNvLCPL11mAbNaqxlDocqSbcVoOtSecVHVk69Rj2k5T3Bw9i24XvsNuO5P+NHQcT/tuOyY92HCYi0FwbJV9hIblUFhFSWOb8hXH+BcKc5cJuM+sNWHzuPGH2DV35QMEIcWVOmjyMQfw3PqPQ58tjny9O2Jz+ic3Om/5FH+ij/yJafgI=tZTbbuMgEIafxpdd2aBmm8skTVqttKpUq1qpNytipoYGgxeT2tmnLwR8oKl6kNorwz8HmPnGJHhVdVea1Oy3oiASlNIuwZcJQlmWzuzHKQevXODUC6XmNDiNQs7/QxB7tz2n0ESORilheB2LhZISChNpRGvVxm4PSsSn1qSEEyEviDhV/3BqWKgC/Rz1a+Al60/OZnNvqUjvHCppGKGqnUh4neCVVsr4VdWtQLjm9X25be/zdIN+/b3j8x05Z+2Crs98ss1nQoYSNEjz0dR3Deib7aNrKUoF2Vqsx8hcVeAYQGd8WsHlzpuYMQ7KwuVAm5Ibtt/+KFRlN1pAU3NJmsYGb/4RSYmPfvPiaOjSUGhjDj0ZrfaSgovPErxsGTeQ16Rw1tbOotWYqUQw+9OeQNuLvwD7TleyySWuwFZv9MHGdfGYHuJtO45K1vNnkzGZBY2E6SyHxCMBuwhl99sJk48wOpL5bkb4TUbHMYlANEarHayUUNoqUknruXzgQryQiOCltNvC0gGrLx07bv/LRTBUnFJ3zKvkx9lIvxE+juHPT+FfvMIefQl7B2x4Oo7ukwcYr58B 2 | -------------------------------------------------------------------------------- /tests/data/space/file with spaces.drawio: -------------------------------------------------------------------------------- 1 | tVRNU8MgEP01OeokodPq0da2zjiO43QcvdKwBiqBCNQk/nqhIR/Y6njQU+DtW5Z9b0mEFkW9Vrikd5IAj9KY1BG6jtI0SeKp/TikaZELFLdArhjxpAHYsA/wYEfbMwI6IBopuWFlCGZSCMhMgGGlZBXSXiQPq5Y4hyNgk2F+jD4xYqjvIp0N+A2wnHaVk+llGylwR/adaIqJrEYQWkZooaQ07aqoF8CdeJ0ubd7qm2h/MQXCnEh41KDutzunSRpzvLW+HEgbWYATEWrTnsCZeG1D1Bin6pU7I13lzND99jyThd0oDrpkAmttk1dvWBDcZnfXeY5RvtNnzex2Rx6qh+Zjt5ycpX2b/fW1aTppldwLAi4/idC8oszApsSZi1Z2mCxGTcF9+LhbL8A7KNvLCPL11mAbNaqxlDocqSbcVoOtSecVHVk69Rj2k5T3Bw9i24XvsNuO5P+NHQcT/tuOyY92HCYi0FwbJV9hIblUFhFSWOb8hXH+BcKc5cJuM+sNWHzuPGH2DV35QMEIcWVOmjyMQfw3PqPQ58tjny9O2Jz+ic3Om/5FH+ij/yJafgI=tZTbbuMgEIafxpdd2aBmm8skTVqttKpUq1qpNytipoYGgxeT2tmnLwR8oKl6kNorwz8HmPnGJHhVdVea1Oy3oiASlNIuwZcJQlmWzuzHKQevXODUC6XmNDiNQs7/QxB7tz2n0ESORilheB2LhZISChNpRGvVxm4PSsSn1qSEEyEviDhV/3BqWKgC/Rz1a+Al60/OZnNvqUjvHCppGKGqnUh4neCVVsr4VdWtQLjm9X25be/zdIN+/b3j8x05Z+2Crs98ss1nQoYSNEjz0dR3Deib7aNrKUoF2Vqsx8hcVeAYQGd8WsHlzpuYMQ7KwuVAm5Ibtt/+KFRlN1pAU3NJmsYGb/4RSYmPfvPiaOjSUGhjDj0ZrfaSgovPErxsGTeQ16Rw1tbOotWYqUQw+9OeQNuLvwD7TleyySWuwFZv9MHGdfGYHuJtO45K1vNnkzGZBY2E6SyHxCMBuwhl99sJk48wOpL5bkb4TUbHMYlANEarHayUUNoqUknruXzgQryQiOCltNvC0gGrLx07bv/LRTBUnFJ3zKvkx9lIvxE+juHPT+FfvMIefQl7B2x4Oo7ukwcYr58B 2 | -------------------------------------------------------------------------------- /tests/data/tree/folder1/file2.1.drawio: -------------------------------------------------------------------------------- 1 | tVRNU8MgEP01OeokodPq0da2zjiO43QcvdKwBiqBCNQk/nqhIR/Y6njQU+DtW5Z9b0mEFkW9Vrikd5IAj9KY1BG6jtI0SeKp/TikaZELFLdArhjxpAHYsA/wYEfbMwI6IBopuWFlCGZSCMhMgGGlZBXSXiQPq5Y4hyNgk2F+jD4xYqjvIp0N+A2wnHaVk+llGylwR/adaIqJrEYQWkZooaQ07aqoF8CdeJ0ubd7qm2h/MQXCnEh41KDutzunSRpzvLW+HEgbWYATEWrTnsCZeG1D1Bin6pU7I13lzND99jyThd0oDrpkAmttk1dvWBDcZnfXeY5RvtNnzex2Rx6qh+Zjt5ycpX2b/fW1aTppldwLAi4/idC8oszApsSZi1Z2mCxGTcF9+LhbL8A7KNvLCPL11mAbNaqxlDocqSbcVoOtSecVHVk69Rj2k5T3Bw9i24XvsNuO5P+NHQcT/tuOyY92HCYi0FwbJV9hIblUFhFSWOb8hXH+BcKc5cJuM+sNWHzuPGH2DV35QMEIcWVOmjyMQfw3PqPQ58tjny9O2Jz+ic3Om/5FH+ij/yJafgI=tZTbbuMgEIafxpdd2aBmm8skTVqttKpUq1qpNytipoYGgxeT2tmnLwR8oKl6kNorwz8HmPnGJHhVdVea1Oy3oiASlNIuwZcJQlmWzuzHKQevXODUC6XmNDiNQs7/QxB7tz2n0ESORilheB2LhZISChNpRGvVxm4PSsSn1qSEEyEviDhV/3BqWKgC/Rz1a+Al60/OZnNvqUjvHCppGKGqnUh4neCVVsr4VdWtQLjm9X25be/zdIN+/b3j8x05Z+2Crs98ss1nQoYSNEjz0dR3Deib7aNrKUoF2Vqsx8hcVeAYQGd8WsHlzpuYMQ7KwuVAm5Ibtt/+KFRlN1pAU3NJmsYGb/4RSYmPfvPiaOjSUGhjDj0ZrfaSgovPErxsGTeQ16Rw1tbOotWYqUQw+9OeQNuLvwD7TleyySWuwFZv9MHGdfGYHuJtO45K1vNnkzGZBY2E6SyHxCMBuwhl99sJk48wOpL5bkb4TUbHMYlANEarHayUUNoqUknruXzgQryQiOCltNvC0gGrLx07bv/LRTBUnFJ3zKvkx9lIvxE+juHPT+FfvMIefQl7B2x4Oo7ukwcYr58B 2 | -------------------------------------------------------------------------------- /tests/data/tree/folder1/file2.2.drawio: -------------------------------------------------------------------------------- 1 | tVRNU8MgEP01OeokodPq0da2zjiO43QcvdKwBiqBCNQk/nqhIR/Y6njQU+DtW5Z9b0mEFkW9Vrikd5IAj9KY1BG6jtI0SeKp/TikaZELFLdArhjxpAHYsA/wYEfbMwI6IBopuWFlCGZSCMhMgGGlZBXSXiQPq5Y4hyNgk2F+jD4xYqjvIp0N+A2wnHaVk+llGylwR/adaIqJrEYQWkZooaQ07aqoF8CdeJ0ubd7qm2h/MQXCnEh41KDutzunSRpzvLW+HEgbWYATEWrTnsCZeG1D1Bin6pU7I13lzND99jyThd0oDrpkAmttk1dvWBDcZnfXeY5RvtNnzex2Rx6qh+Zjt5ycpX2b/fW1aTppldwLAi4/idC8oszApsSZi1Z2mCxGTcF9+LhbL8A7KNvLCPL11mAbNaqxlDocqSbcVoOtSecVHVk69Rj2k5T3Bw9i24XvsNuO5P+NHQcT/tuOyY92HCYi0FwbJV9hIblUFhFSWOb8hXH+BcKc5cJuM+sNWHzuPGH2DV35QMEIcWVOmjyMQfw3PqPQ58tjny9O2Jz+ic3Om/5FH+ij/yJafgI=tZTbbuMgEIafxpdd2aBmm8skTVqttKpUq1qpNytipoYGgxeT2tmnLwR8oKl6kNorwz8HmPnGJHhVdVea1Oy3oiASlNIuwZcJQlmWzuzHKQevXODUC6XmNDiNQs7/QxB7tz2n0ESORilheB2LhZISChNpRGvVxm4PSsSn1qSEEyEviDhV/3BqWKgC/Rz1a+Al60/OZnNvqUjvHCppGKGqnUh4neCVVsr4VdWtQLjm9X25be/zdIN+/b3j8x05Z+2Crs98ss1nQoYSNEjz0dR3Deib7aNrKUoF2Vqsx8hcVeAYQGd8WsHlzpuYMQ7KwuVAm5Ibtt/+KFRlN1pAU3NJmsYGb/4RSYmPfvPiaOjSUGhjDj0ZrfaSgovPErxsGTeQ16Rw1tbOotWYqUQw+9OeQNuLvwD7TleyySWuwFZv9MHGdfGYHuJtO45K1vNnkzGZBY2E6SyHxCMBuwhl99sJk48wOpL5bkb4TUbHMYlANEarHayUUNoqUknruXzgQryQiOCltNvC0gGrLx07bv/LRTBUnFJ3zKvkx9lIvxE+juHPT+FfvMIefQl7B2x4Oo7ukwcYr58B 2 | -------------------------------------------------------------------------------- /tests/data/tree/folder2/folder3/file3.drawio: -------------------------------------------------------------------------------- 1 | tVRNU8MgEP01OeokodPq0da2zjiO43QcvdKwBiqBCNQk/nqhIR/Y6njQU+DtW5Z9b0mEFkW9Vrikd5IAj9KY1BG6jtI0SeKp/TikaZELFLdArhjxpAHYsA/wYEfbMwI6IBopuWFlCGZSCMhMgGGlZBXSXiQPq5Y4hyNgk2F+jD4xYqjvIp0N+A2wnHaVk+llGylwR/adaIqJrEYQWkZooaQ07aqoF8CdeJ0ubd7qm2h/MQXCnEh41KDutzunSRpzvLW+HEgbWYATEWrTnsCZeG1D1Bin6pU7I13lzND99jyThd0oDrpkAmttk1dvWBDcZnfXeY5RvtNnzex2Rx6qh+Zjt5ycpX2b/fW1aTppldwLAi4/idC8oszApsSZi1Z2mCxGTcF9+LhbL8A7KNvLCPL11mAbNaqxlDocqSbcVoOtSecVHVk69Rj2k5T3Bw9i24XvsNuO5P+NHQcT/tuOyY92HCYi0FwbJV9hIblUFhFSWOb8hXH+BcKc5cJuM+sNWHzuPGH2DV35QMEIcWVOmjyMQfw3PqPQ58tjny9O2Jz+ic3Om/5FH+ij/yJafgI=tZTbbuMgEIafxpdd2aBmm8skTVqttKpUq1qpNytipoYGgxeT2tmnLwR8oKl6kNorwz8HmPnGJHhVdVea1Oy3oiASlNIuwZcJQlmWzuzHKQevXODUC6XmNDiNQs7/QxB7tz2n0ESORilheB2LhZISChNpRGvVxm4PSsSn1qSEEyEviDhV/3BqWKgC/Rz1a+Al60/OZnNvqUjvHCppGKGqnUh4neCVVsr4VdWtQLjm9X25be/zdIN+/b3j8x05Z+2Crs98ss1nQoYSNEjz0dR3Deib7aNrKUoF2Vqsx8hcVeAYQGd8WsHlzpuYMQ7KwuVAm5Ibtt/+KFRlN1pAU3NJmsYGb/4RSYmPfvPiaOjSUGhjDj0ZrfaSgovPErxsGTeQ16Rw1tbOotWYqUQw+9OeQNuLvwD7TleyySWuwFZv9MHGdfGYHuJtO45K1vNnkzGZBY2E6SyHxCMBuwhl99sJk48wOpL5bkb4TUbHMYlANEarHayUUNoqUknruXzgQryQiOCltNvC0gGrLx07bv/LRTBUnFJ3zKvkx9lIvxE+juHPT+FfvMIefQl7B2x4Oo7ukwcYr58B 2 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to contribute to Draw.io Export 2 | 3 | ## Did you find a bug 4 | 5 | * **Do not open up a GitHub issue if the bug is a security vulnerability**, and instead to refer to our [security policy][1]. 6 | 7 | * **Ensure the bug was not already reported** by searching on GitHub under [Issues][2]. 8 | 9 | * If you're unable to find an open issue addressing the problem, [open a 'Bug' issue][4]. 10 | Be sure to include a **title and clear description**, as much relevant information as possible, and a **code sample** or an **executable test case** demonstrating the expected behavior that is not occurring. 11 | 12 | ## Did you write a patch that fixes a bug 13 | 14 | * Open a new GitHub pull request with the patch. 15 | 16 | * Ensure the PR description clearly describes the problem and solution. 17 | Include the relevant issue number if applicable. 18 | 19 | ## Do you intend to add a new feature or change an existing one 20 | 21 | * Suggest your change by [opening a 'Feature request' issue][5] 22 | 23 | ## Do you have questions about the source code 24 | 25 | * [open an issue][3] with your question. 26 | 27 | Thanks! 28 | 29 | [1]: https://github.com/rlespinasse/drawio-export/security/policy 30 | [2]: https://github.com/rlespinasse/drawio-export/issues 31 | [3]: https://github.com/rlespinasse/drawio-export/issues/new 32 | [4]: https://github.com/rlespinasse/drawio-export/issues/new?assignees=&labels=bug&template=bug_report.md&title= 33 | [5]: https://github.com/rlespinasse/drawio-export/issues/new?assignees=&labels=enhancement&template=feature_request.md&title= -------------------------------------------------------------------------------- /README.adoc: -------------------------------------------------------------------------------- 1 | = Draw.io Export 2 | 3 | Export Draw.io diagrams using docker 4 | 5 | == Features 6 | 7 | * Recursive export 8 | * Partial export (newer, or based on git reference) 9 | * Additional export formats with link extraction 10 | 11 | == Supported Export formats 12 | 13 | * **draw.io** export formats : jpg, pdf, png, svg, vsdx, and xml 14 | * **drawio-exporter** additional formats 15 | ** adoc - Export in png and create an additional asciidoc file (with support external links). 16 | ** md - Export in png and create an additional markdown file (with support external links). 17 | 18 | == Additional fonts 19 | 20 | Check installed fonts list from https://github.com/rlespinasse/docker-drawio-desktop-headless[drawio-desktop-headless] docker base image. 21 | 22 | NOTE: Want a new font package, modify the https://github.com/rlespinasse/docker-drawio-desktop-headless[drawio-desktop-headless] project. 23 | 24 | == Installation 25 | 26 | [source,bash] 27 | ---- 28 | docker pull rlespinasse/drawio-export 29 | ---- 30 | 31 | == Usage 32 | 33 | .Print the available options 34 | [source,bash] 35 | ---- 36 | docker run -it rlespinasse/drawio-export --help 37 | ---- 38 | 39 | .Simple run with default options 40 | [source,bash] 41 | ---- 42 | $ cd directory-with-drawio-files 43 | $ docker run -it -v $(pwd):/data rlespinasse/drawio-export 44 | + export file : ./file1.drawio 45 | - export page 1 : Page-1 46 | \ generate pdf file 47 | - export page 2 : Page-2 48 | \ generate pdf file 49 | ---- 50 | 51 | == Build on top of 52 | 53 | * https://github.com/rlespinasse/docker-drawio-desktop-headless[**rlespinasse/drawio-export-headless**] as base docker image to use Draw.io Desktop for its command lines, 54 | * https://github.com/rlespinasse/drawio-exporter[**drawio-exporter**] as backend for export capabilities. 55 | 56 | == Used by 57 | 58 | * GitHub Action https://github.com/rlespinasse/drawio-export-action[**drawio-export-action**] : which is build on top of **drawio-export** docker image. 59 | 60 | == Contributing 61 | 62 | Pull requests are welcome. 63 | For major changes, please open an issue first to discuss what you would like to change. 64 | 65 | Please make sure to update tests as appropriate. 66 | -------------------------------------------------------------------------------- /tests/data/types/nominal.drawio: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /tests/data/vscode/vscode.drawio: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /tests/data/issue-140/page-index-mismatch.drawio: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /.github/workflows/drawio-export.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Build And Release 3 | 4 | on: 5 | pull_request: 6 | push: 7 | branches: 8 | - v4.x 9 | 10 | permissions: read-all 11 | 12 | jobs: 13 | build: 14 | runs-on: ubuntu-latest 15 | 16 | concurrency: 17 | group: build-${{ github.ref }}-${{ github.event_name }} 18 | cancel-in-progress: true 19 | 20 | steps: 21 | # Setup 22 | - uses: actions/checkout@v6 23 | with: 24 | fetch-depth: 0 25 | 26 | - uses: actions/setup-node@v6 27 | 28 | - uses: rlespinasse/github-slug-action@v5 29 | 30 | - name: Build docker image 31 | run: make build 32 | shell: bash 33 | env: 34 | DOCKER_IMAGE: ${{ github.repository }}:${{ env.GITHUB_REF_SLUG }} 35 | 36 | - name: Setup CI for test 37 | run: make test-ci-setup 38 | shell: bash 39 | 40 | - name: Test docker image 41 | run: make test-ci 42 | shell: bash 43 | env: 44 | DOCKER_IMAGE: ${{ github.repository }}:${{ env.GITHUB_REF_SLUG }} 45 | 46 | - name: Test docker image // Store output logs 47 | uses: actions/upload-artifact@v5 48 | with: 49 | name: test-docker-image-logs 50 | path: "tests/output/*.log" 51 | if: ${{ always() }} 52 | 53 | - name: Test docker image // Store output files 54 | uses: actions/upload-artifact@v5 55 | with: 56 | name: test-docker-image-files 57 | path: | 58 | tests/data 59 | !tests/data/*.drawio 60 | !tests/data/*/*.drawio 61 | if: ${{ always() }} 62 | 63 | build-multiarch: 64 | runs-on: ubuntu-latest 65 | 66 | concurrency: 67 | group: build-multiarch-${{ github.ref }}-${{ github.event_name }} 68 | cancel-in-progress: true 69 | 70 | steps: 71 | - uses: actions/checkout@v6 72 | 73 | - uses: rlespinasse/github-slug-action@v5 74 | 75 | - name: Set up QEMU 76 | uses: docker/setup-qemu-action@v3 77 | with: 78 | platforms: "arm64,arm" 79 | 80 | - name: Set up Docker Buildx 81 | uses: docker/setup-buildx-action@v3 82 | 83 | - name: Build docker image 84 | run: make build-multiarch 85 | shell: bash 86 | env: 87 | DOCKER_IMAGE: ${{ github.repository }}:${{ env.GITHUB_REF_SLUG }} 88 | 89 | release: 90 | runs-on: ubuntu-latest 91 | 92 | needs: 93 | - build 94 | - build-multiarch 95 | 96 | permissions: 97 | contents: write 98 | issues: write 99 | id-token: write 100 | packages: write 101 | 102 | concurrency: 103 | group: release-${{ github.ref }}-${{ github.event_name }} 104 | 105 | steps: 106 | - uses: actions/checkout@v6 107 | 108 | - name: Release this docker image 109 | uses: rlespinasse/release-that@v1 110 | with: 111 | github-token: ${{ secrets.GH_TOKEN }} 112 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone, regardless of age, body 7 | size, visible or invisible disability, ethnicity, sex characteristics, gender 8 | identity and expression, level of experience, education, socio-economic status, 9 | nationality, personal appearance, race, religion, or sexual identity 10 | and orientation. 11 | 12 | We pledge to act and interact in ways that contribute to an open, welcoming, 13 | diverse, inclusive, and healthy community. 14 | 15 | ## Our Standards 16 | 17 | Examples of behavior that contributes to a positive environment for our 18 | community include: 19 | 20 | * Demonstrating empathy and kindness toward other people 21 | * Being respectful of differing opinions, viewpoints, and experiences 22 | * Giving and gracefully accepting constructive feedback 23 | * Accepting responsibility and apologizing to those affected by our mistakes, 24 | and learning from the experience 25 | * Focusing on what is best not just for us as individuals, but for the 26 | overall community 27 | 28 | Examples of unacceptable behavior include: 29 | 30 | * The use of sexualized language or imagery, and sexual attention or 31 | advances of any kind 32 | * Trolling, insulting or derogatory comments, and personal or political attacks 33 | * Public or private harassment 34 | * Publishing others' private information, such as a physical or email 35 | address, without their explicit permission 36 | * Other conduct which could reasonably be considered inappropriate in a 37 | professional setting 38 | 39 | ## Enforcement Responsibilities 40 | 41 | Community leaders are responsible for clarifying and enforcing our standards of 42 | acceptable behavior and will take appropriate and fair corrective action in 43 | response to any behavior that they deem inappropriate, threatening, offensive, 44 | or harmful. 45 | 46 | Community leaders have the right and responsibility to remove, edit, or reject 47 | comments, commits, code, wiki edits, issues, and other contributions that are 48 | not aligned to this Code of Conduct, and will communicate reasons for moderation 49 | decisions when appropriate. 50 | 51 | ## Scope 52 | 53 | This Code of Conduct applies within all community spaces, and also applies when 54 | an individual is officially representing the community in public spaces. 55 | Examples of representing our community include using an official e-mail address, 56 | posting via an official social media account, or acting as an appointed 57 | representative at an online or offline event. 58 | 59 | ## Enforcement 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 62 | reported to the community leaders responsible for enforcement at 63 | romain.lespinasse@gmail.com. 64 | All complaints will be reviewed and investigated promptly and fairly. 65 | 66 | All community leaders are obligated to respect the privacy and security of the 67 | reporter of any incident. 68 | 69 | ## Enforcement Guidelines 70 | 71 | Community leaders will follow these Community Impact Guidelines in determining 72 | the consequences for any action they deem in violation of this Code of Conduct: 73 | 74 | ### 1. Correction 75 | 76 | **Community Impact**: Use of inappropriate language or other behavior deemed 77 | unprofessional or unwelcome in the community. 78 | 79 | **Consequence**: A private, written warning from community leaders, providing 80 | clarity around the nature of the violation and an explanation of why the 81 | behavior was inappropriate. A public apology may be requested. 82 | 83 | ### 2. Warning 84 | 85 | **Community Impact**: A violation through a single incident or series 86 | of actions. 87 | 88 | **Consequence**: A warning with consequences for continued behavior. No 89 | interaction with the people involved, including unsolicited interaction with 90 | those enforcing the Code of Conduct, for a specified period of time. This 91 | includes avoiding interactions in community spaces as well as external channels 92 | like social media. Violating these terms may lead to a temporary or 93 | permanent ban. 94 | 95 | ### 3. Temporary Ban 96 | 97 | **Community Impact**: A serious violation of community standards, including 98 | sustained inappropriate behavior. 99 | 100 | **Consequence**: A temporary ban from any sort of interaction or public 101 | communication with the community for a specified period of time. No public or 102 | private interaction with the people involved, including unsolicited interaction 103 | with those enforcing the Code of Conduct, is allowed during this period. 104 | Violating these terms may lead to a permanent ban. 105 | 106 | ### 4. Permanent Ban 107 | 108 | **Community Impact**: Demonstrating a pattern of violation of community 109 | standards, including sustained inappropriate behavior, harassment of an 110 | individual, or aggression toward or disparagement of classes of individuals. 111 | 112 | **Consequence**: A permanent ban from any sort of public interaction within 113 | the community. 114 | 115 | ## Attribution 116 | 117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 118 | version 2.0, available at 119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. 120 | 121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct 122 | enforcement ladder](https://github.com/mozilla/diversity). 123 | 124 | [homepage]: https://www.contributor-covenant.org 125 | 126 | For answers to common questions about this code of conduct, see the FAQ at 127 | https://www.contributor-covenant.org/faq. Translations are available at 128 | https://www.contributor-covenant.org/translations. 129 | -------------------------------------------------------------------------------- /tests/data/shapes/shapes.drawio: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | --------------------------------------------------------------------------------