{"id":33936090,"url":"https://github.com/jsinger67/id-tree-layout","last_synced_at":"2026-04-06T06:31:17.903Z","repository":{"id":62440476,"uuid":"302647660","full_name":"jsinger67/id-tree-layout","owner":"jsinger67","description":"A Rust library to visualize trees from the 'id_tree' crate.","archived":false,"fork":false,"pushed_at":"2022-09-27T15:55:03.000Z","size":71,"stargazers_count":8,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-12-14T01:49:32.572Z","etag":null,"topics":["algorithms","data-structures","rust","tree","visualization"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jsinger67.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-10-09T13:22:07.000Z","updated_at":"2025-05-30T14:47:39.000Z","dependencies_parsed_at":"2022-11-01T21:53:15.066Z","dependency_job_id":null,"html_url":"https://github.com/jsinger67/id-tree-layout","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/jsinger67/id-tree-layout","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jsinger67%2Fid-tree-layout","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jsinger67%2Fid-tree-layout/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jsinger67%2Fid-tree-layout/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jsinger67%2Fid-tree-layout/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jsinger67","download_url":"https://codeload.github.com/jsinger67/id-tree-layout/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jsinger67%2Fid-tree-layout/sbom","scorecard":{"id":538407,"data":{"date":"2025-08-11","repo":{"name":"github.com/jsinger67/id-tree-layout","commit":"5de114addb2964a71db988cef0efe9dc0c7cbc66"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.8,"checks":[{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/rust.yml:18: update your workflow using https://app.stepsecurity.io/secureworkflow/jsinger67/id-tree-layout/rust.yml/main?enable=pin","Info:   0 out of   1 GitHub-owned GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/rust.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}}]},"last_synced_at":"2025-08-20T07:35:52.639Z","repository_id":62440476,"created_at":"2025-08-20T07:35:52.640Z","updated_at":"2025-08-20T07:35:52.640Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31463011,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-05T21:22:52.476Z","status":"online","status_checked_at":"2026-04-06T02:00:07.287Z","response_time":112,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["algorithms","data-structures","rust","tree","visualization"],"created_at":"2025-12-12T14:04:12.228Z","updated_at":"2026-04-06T06:31:17.898Z","avatar_url":"https://github.com/jsinger67.png","language":"Rust","readme":"[![Build Status](https://travis-ci.org/jsinger67/id-tree-layout.svg?branch=main)](https://travis-ci.org/jsinger/id-tree-layout)\n[![Docs.rs](https://docs.rs/id_tree_layout/badge.svg)](https://docs.rs/id_tree_layout)\n[![Crates.io](https://img.shields.io/crates/v/id_tree_layout.svg)](https://crates.io/crates/id_tree_layout)\n\n# id_tree_layout\n\nA library to visualize tree structures, tailored for the\n*[id_tree](https://github.com/iwburns/id-tree)* crate.\n\n## Overview\n\nThis crate evolved as a side-product while working on a parser generator.\n\nTo check the correctness of generated parsers I needed to visualize large parse trees.\nThe `id_tree`'s own `write_formatted` method is quite handy for smaller trees but quickly reaches its limits when trees start to grow.\n\nSo I wanted to have something that is more visually comprehensible.\n\nAnd here is what the result may look like:\n\n![example.svg](./docs/example.svg)\n\nIt turned out that the task to visualize trees is a universal one. So I decided to provide a\nseparate crate for the community.\n\nWhile striving for universality it was not easy to completely abstract from the concrete tree data\nstructure people might ever use. Thus I decided to use the well known `id_tree`'s tree\nimplementation as the foundation for this crate.\n\nThe other abstraction I wanted to face was the concrete node data type and how it should be\npresented for a tree visualization. To resort to the implementation of the node's data type's\n`Display` trait seemed not to be specific enough. It would imply that the visualization of a\nnode in a graph is the same as the one used on console display.\n\nAs a solution with lowest impact on users' code I decided to demand from the user to implement one single\ntrait for his node's data type: `Visualize`. This trait only contains two methods and only one of\nthem is mandatory to implement.\n\nWith this in mind there are two major restrictions one should know when to consider this crate to\nvisualize trees:\n\n* This crate only works together with tree types provided by the `id_tree` crate.\n* The user of the crate needs to implement the `Visualize` trait for his node's data type.\n\nThe library provides a third abstraction. It is about how an embedding of nodes in the plane is\npresented to the user, i.e. in which format the embedding is converted in the end. For the sake of\nsimplicity the `id_tree_layout` crate offers a simple default solution for this task, the SvgDrawer\ntype. It provides elementary representation of the embedding in SVG format. But if the user wants\nto use its own realization, for instance to print the embedding onto a bitmap, he can integrate\ninto the graph generation easily. For this he needs to implement his own drawer algorithm and\nimplement the `Drawer` trait for it. Then he can use the `Layouter`'s `with_drawer` method to supply it\nto the drawing procedure.\n\n## Example Usage\n\n```rust\nuse id_tree::InsertBehavior::{AsRoot, UnderNode};\nuse id_tree::{Node, NodeId, Tree, TreeBuilder};\nuse id_tree_layout::{Layouter, Visualize};\n\nstruct MyNodeData(i32);\n\n// You need to implement id_tree_layout::Visualize for your nodes data type.\n// This way you provide basic formatting information.\nimpl Visualize for MyNodeData {\n    fn visualize(\u0026self) -\u003e std::string::String {\n        // We simply convert the i32 value to string here.\n        self.0.to_string()\n    }\n    fn emphasize(\u0026self) -\u003e bool {\n        // This simply emphasizes only the leaf nodes.\n        // It only works for this example.\n        self.0 \u003e 1\n    }\n}\n\nfn main() {\n    //      0\n    //     / \\\n    //    1   2\n    //   / \\\n    //  3   4\n    let mut tree: Tree\u003cMyNodeData\u003e = TreeBuilder::new().with_node_capacity(5).build();\n\n    let root_id: NodeId = tree.insert(Node::new(MyNodeData(0)), AsRoot).unwrap();\n    let child_id: NodeId = tree.insert(Node::new(MyNodeData(1)), UnderNode(\u0026root_id)).unwrap();\n    tree.insert(Node::new(MyNodeData(2)), UnderNode(\u0026root_id)).unwrap();\n    tree.insert(Node::new(MyNodeData(3)), UnderNode(\u0026child_id)).unwrap();\n    tree.insert(Node::new(MyNodeData(4)), UnderNode(\u0026child_id)).unwrap();\n\n    // Here comes the visualization part.\n    Layouter::new(\u0026tree)\n        .with_file_path(std::path::Path::new(\"test.svg\"));\n        .write()\n        .expect(\"Failed writing layout\")\n}\n\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjsinger67%2Fid-tree-layout","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjsinger67%2Fid-tree-layout","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjsinger67%2Fid-tree-layout/lists"}