{"id":20601385,"url":"https://github.com/tmccarthy/tmm-scala-plotly","last_synced_at":"2026-06-05T10:31:50.066Z","repository":{"id":57715044,"uuid":"279055816","full_name":"tmccarthy/tmm-scala-plotly","owner":"tmccarthy","description":"Yet another Scala API for Plotly.js","archived":false,"fork":false,"pushed_at":"2021-03-08T10:34:54.000Z","size":231,"stargazers_count":1,"open_issues_count":3,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-06T16:19:12.992Z","etag":null,"topics":["plotly","plotlyjs","scala"],"latest_commit_sha":null,"homepage":"","language":"Scala","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tmccarthy.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-07-12T12:03:46.000Z","updated_at":"2024-12-09T19:54:17.000Z","dependencies_parsed_at":"2022-09-02T22:01:33.020Z","dependency_job_id":null,"html_url":"https://github.com/tmccarthy/tmm-scala-plotly","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/tmccarthy/tmm-scala-plotly","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tmccarthy%2Ftmm-scala-plotly","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tmccarthy%2Ftmm-scala-plotly/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tmccarthy%2Ftmm-scala-plotly/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tmccarthy%2Ftmm-scala-plotly/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tmccarthy","download_url":"https://codeload.github.com/tmccarthy/tmm-scala-plotly/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tmccarthy%2Ftmm-scala-plotly/sbom","scorecard":{"id":889772,"data":{"date":"2025-08-11","repo":{"name":"github.com/tmccarthy/tmm-scala-plotly","commit":"501a3474ac30facee253e02d3825a6c0ac524144"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.4,"checks":[{"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":"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":"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":"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":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/ci.yml:1","Warn: no topLevel permission defined: .github/workflows/clean.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":"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":"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":"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/ci.yml:31: update your workflow using https://app.stepsecurity.io/secureworkflow/tmccarthy/tmm-scala-plotly/ci.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/ci.yml:36: update your workflow using https://app.stepsecurity.io/secureworkflow/tmccarthy/tmm-scala-plotly/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:41: update your workflow using https://app.stepsecurity.io/secureworkflow/tmccarthy/tmm-scala-plotly/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:61: update your workflow using https://app.stepsecurity.io/secureworkflow/tmccarthy/tmm-scala-plotly/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:78: update your workflow using https://app.stepsecurity.io/secureworkflow/tmccarthy/tmm-scala-plotly/ci.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/ci.yml:83: update your workflow using https://app.stepsecurity.io/secureworkflow/tmccarthy/tmm-scala-plotly/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:88: update your workflow using https://app.stepsecurity.io/secureworkflow/tmccarthy/tmm-scala-plotly/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:100: update your workflow using https://app.stepsecurity.io/secureworkflow/tmccarthy/tmm-scala-plotly/ci.yml/master?enable=pin","Info:   0 out of   6 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   2 third-party 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":"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":"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: Apache License 2.0: 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":"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":"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":"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":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"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-24T11:20:46.739Z","repository_id":57715044,"created_at":"2025-08-24T11:20:46.739Z","updated_at":"2025-08-24T11:20:46.739Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33939226,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-05T02:00:06.157Z","response_time":120,"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":["plotly","plotlyjs","scala"],"created_at":"2024-11-16T09:09:51.832Z","updated_at":"2026-06-05T10:31:50.007Z","avatar_url":"https://github.com/tmccarthy.png","language":"Scala","funding_links":[],"categories":[],"sub_categories":[],"readme":"# `tmm-scala-plotly`\n[![CircleCI](https://circleci.com/gh/tmccarthy/tmm-scala-plotly/tree/master.svg?style=svg)](https://circleci.com/gh/tmccarthy/tmm-scala-plotly/tree/master)\n[![Maven Central](https://img.shields.io/maven-central/v/au.id.tmm.tmm-scala-plotly/tmm-scala-plotly-core_2.13.svg)](https://repo.maven.apache.org/maven2/au/id/tmm/tmm-scala-plotly/tmm-scala-plotly-core_2.13/)\n\nYet another library for integration between [Plotly](https://plotly.com/javascript/) and Scala.\n\n## Getting started\n\nIn your `build.sbt` file.\n\n```scala\ntmmScalaPlotlyVersion = 0.0.2\n\nlibraryDependencies += \"au.id.tmm.tmm-scala-plotly\" %% \"tmm-scala-plotly-core\" % tmmScalaPlotlyVersion\n```\n\n## Rationale\n\nThis library is a representation of the [Plotly JavaScript API](https://plotly.com/javascript/) in Scala. It is a\nhand-written and almost complete representation of the Plotly API as documented in [DefinitelyTyped](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/53e3fb2/types/plotly.js/index.d.ts),\nand informed by the official documentation.\n\nThere are already at least two other libraries that provide Scala integration for Plotly:\n\n* [`facultyai/scala-plotly-client`](https://github.com/facultyai/scala-plotly-client) is an older library that is \n  documented on the [Plotly website](https://plotly.com/scala/). It does not appear to be under active development.\n* [`alexarchambault/plotly-scala`](https://github.com/alexarchambault/plotly-scala/), which is a modern and mature \n  offering.\n\nMy advice would be that if you are looking for a library to use Plotly from Scala, you should use [`alexarchambault/plotly-scala`](https://github.com/alexarchambault/plotly-scala/).\nIt is more mature and better tested than this library, and I've had a lot of success with it.\n\nThis library has a couple of key philosophical differences with `alexarchambault/plotly-scala`, which is why I decided \nto write it:\n\n* **Completeness:** This library is an almost exhaustive representation of the Plotly Javascript API. You should be able \n  to produce every kind of plot supported by the official Javascript library.\n* **Self-documenting:** This library makes extensive use of value classes and algebraic data types to attempt to clarify \n  the meaning of fields within the Plotly API. Implicit conversions are opt-in and are intended only for ease-of-use \n  (see [below](#usage)).\n* **Incorrect:** This library does not (yet) use the power of the Scala type system to ensure valid use of Plotly. For \n  example, you can provide `z` co-ordinates to two-dimensional scatter plots. This is an intentional tradeoff to make it\n  simpler to produce an exhaustive representation of the Javascript API.\n* **No ScalaJS support:** I don't use ScalaJS, so I haven't provided support for it.\n* **Circe as a first-class citizen:** This project uses [`circe`](https://github.com/circe/circe) to encode the model to \n  Json. The `circe` integrations are deliberately exposed by the main library to give clients as much flexibility as \n  possible when encoding.\n  \nNote that I've hand-written this interface over Plotly but have done almost no thorough testing. Many of the corners of \nthis library are unlikely to have seen any use. *Caveat emptor*.\n\n## Usage\n\nTo draw a pie chart:\n\n```scala\nimport au.id.tmm.plotly._\nimport au.id.tmm.plotly.model._\nimport au.id.tmm.plotly.model.utilities._\n\nval (labels, values, colours) = List(\n  (\"Coalition\", 5_906_875, Color(\"blue\")),\n  (\"Labor\", 4_752_160, Color(\"red\")),\n  (\"Greens\", 1_482_923, Color(\"green\")),\n  (\"Other\", 2_111_435, Color(\"grey\")),\n).unzip3\n\nval plot = Plot(\n  data = List(\n    Trace(\n      `type` = OptArg.Of(Trace.Type.Pie),\n      labels = OptArg.Of(DataArray.OfStrings(labels)),\n      values = OptArg.Of(DataArray.OfInts(values)),\n      marker = OptArg.Of(\n        PlotMarker(\n          colors = OptArg.Of(colours),\n        ),\n      ),\n    ),\n  ),\n  layout = OptArg.Of(\n    Layout(\n      title = OptArg.Of(\n        Layout.Title(\n          text = OptArg.Of(\"2019 primary votes\"),\n        ),\n      ),\n      width = OptArg.Of(300d),\n      height = OptArg.Of(300d),\n    ),\n  ),\n)\n\nPlotting.openInBrowser(plot)\n```\n\n![A pie chart showing the primary votes at the 2019 Australian Federal Election](/docs/pie.png)\n\n### Implicit conversions for ergonomics\n\nIn the above you should note that we make use of types like `OptArg` and `DataArray`. These allow us to have explicit \nand type-safe representations of optional parameters and the different types of data array respectively. Using these\neverywhere gets tiring, so we can import `au.id.tmm.plotly.syntax._` to make things a little less verbose \nwhile retaining type safety. With this import, the above becomes:\n\n```scala\nimport au.id.tmm.plotly._\nimport au.id.tmm.plotly.model._\nimport au.id.tmm.plotly.syntax._\n\nval (labels, values, colours) = List(\n  (\"Coalition\", 5_906_875, Color(\"blue\")),\n  (\"Labor\", 4_752_160, Color(\"red\")),\n  (\"Greens\", 1_482_923, Color(\"green\")),\n  (\"Other\", 2_111_435, Color(\"grey\")),\n).unzip3\n\nval plot = Plot(\n  data = List(\n    Trace(\n      `type` = Trace.Type.Pie,\n      labels = labels,\n      values = values,\n      marker = PlotMarker(colors = colours),\n    ),\n  ),\n  layout = Layout(\n    title = Layout.Title(text = \"2019 primary votes\"),\n    width = 300,\n    height = 300,\n  ),\n)\n\nPlotting.openInBrowser(plot)\n```\n\n### Dedicated trace interfaces\n\nAs discussed in the [Rationale section above](#Rationale), the [`Trace`](/core/src/main/scala/au/id/tmm/plotly/model/Trace.scala) \nclass provides an almost-exhaustive representation of the Plotly Javascript interface. While this allows us to use most\nof the features of Plotly, it also allows us to provide useless or invalid parameters. For example, we could provide the\n`z` co-ordinates for a two-dimensional scatter plot.\n\nAs a partial solution to this, the project includes some dedicated constructors for traces based on the trace type. \nThese are available in the [`au.id.tmm.plotly.model.traceinterfaces`](/core/src/main/scala/au/id/tmm/plotly/model/traceinterfaces)\npackage. For example, an interface is provided for sunburst plots and is demoed in [the examples project](/examples/src/main/scala/au/id/tmm/plotly/examples/Sunburst.scala).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftmccarthy%2Ftmm-scala-plotly","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftmccarthy%2Ftmm-scala-plotly","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftmccarthy%2Ftmm-scala-plotly/lists"}