diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 3258812..48e9c29 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -50,34 +50,34 @@ jobs: fail_ci_if_error: false # token: ${{secrets.CODECOV_TOKEN}} - # docs: - # name: πŸ“– Update docs - # runs-on: ubuntu-latest - # permissions: - # contents: read - # pages: write - # id-token: write - # # Allow one concurrent deployment - # concurrency: - # group: "pages" - # cancel-in-progress: true - # environment: - # name: github-pages - # url: ${{ steps.deployment.outputs.page_url }} - # steps: - # - uses: actions/checkout@v4 - # - run: bash ./scripts/docs-install.sh + docs: + name: πŸ“– Update docs + runs-on: ubuntu-latest + permissions: + contents: read + pages: write + id-token: write + # Allow one concurrent deployment + concurrency: + group: "pages" + cancel-in-progress: true + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + steps: + - uses: actions/checkout@v4 + - run: bash ./scripts/docs-install.sh - # - run: bash ./scripts/docs-build.sh + - run: bash ./scripts/docs-build.sh - # - name: Setup Pages - # uses: actions/configure-pages@v3 + - name: Setup Pages + uses: actions/configure-pages@v3 - # - name: Upload artifact - # uses: actions/upload-pages-artifact@v1 - # with: - # path: './target/doc' + - name: Upload artifact + uses: actions/upload-pages-artifact@v1 + with: + path: './target/doc' - # - name: Deploy to GitHub Pages - # id: deployment - # uses: actions/deploy-pages@v2 + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v2 diff --git a/book.toml b/book.toml new file mode 100644 index 0000000..70ccff2 --- /dev/null +++ b/book.toml @@ -0,0 +1,30 @@ +[book] +authors = [ + "Charles Tapley Hoyt ", + "Vincent Emonet ", +] +language = "en" +multilingual = false +src = "./lib/docs" +title = "CURIEs" +description = "A cross-platform library for idiomatic conversion between URIs and compact URIs (CURIEs)" + +[build] +build-dir = "./target/doc" +create-missing = false + +[preprocessor] + +[preprocessor.admonish] +command = "mdbook-admonish" +assets_version = "3.0.1" # do not edit: managed by `mdbook-admonish install` + +[preprocessor.pagetoc] + +[output.html] +git-repository-url = "https://github.com/biopragmatics/curies.rs" +additional-css = [ + "theme/mdbook-admonish.css", + "theme/pagetoc.css", +] +additional-js = ["theme/pagetoc.js"] diff --git a/js/index.html b/js/index.html index 0d5fe4f..3f0f357 100644 --- a/js/index.html +++ b/js/index.html @@ -2,11 +2,10 @@ - CURIEs dev + CURIEs example -

DOID:

@@ -19,6 +18,7 @@ console.log(rec1.toString()); console.log(rec1.toJs()); + // Populate the Converter with records, or import existing converters: // const converter = new Converter(); // converter.addRecord(rec1); diff --git a/lib/docs/SUMMARY.md b/lib/docs/SUMMARY.md new file mode 100644 index 0000000..b44c7da --- /dev/null +++ b/lib/docs/SUMMARY.md @@ -0,0 +1,7 @@ +# Summary + +- [Introduction](introduction.md) +- [Use Rust crate](use_rust.md) +- [Use Python package](use_python.md) +- [Use NPM package](use_javascript.md) +- [Contributing](contributing.md) diff --git a/lib/docs/contributing.md b/lib/docs/contributing.md new file mode 100644 index 0000000..635dbb1 --- /dev/null +++ b/lib/docs/contributing.md @@ -0,0 +1,179 @@ +# πŸ› οΈ Contributing + +The usual process to make a contribution is to: + +1. Check for existing related [issues on GitHub](https://github.com/biopragmatics/curies.rs/issues) +2. [Fork](https://github.com/biopragmatics/curies.rs/fork) the repository and create a new branch +3. Make your changes +4. Make sure formatting, linting and tests passes. +5. Add tests if possible to cover the lines you added. +6. Commit, and send a Pull Request. + +## οΈπŸ—ΊοΈ Architecture details + +### πŸ—ƒοΈ Folder structure + +``` +curies.rs/ +β”œβ”€β”€ lib/ +β”‚ β”œβ”€β”€ src/ +β”‚ β”‚ └── πŸ¦€ Source code for the core Rust crate. +β”‚ β”œβ”€β”€ tests/ +β”‚ β”‚ └── πŸ§ͺ Tests for the core Rust crate. +β”‚ └── docs/ +β”‚ └── πŸ“– Markdown and HTML files for the documentation website. +β”œβ”€β”€ python/ +β”‚ └── 🐍 Python bindings for interacting with the Rust crate. +β”œβ”€β”€ js/ +β”‚ └── 🌐 JavaScript bindings for integrating into JS environments. +β”œβ”€β”€ scripts/ +β”‚ └── πŸ› οΈ Development scripts (build docs, testing). +└── .github/ + └── workflows/ + └── βš™οΈ Automated CI/CD workflows. +``` + +## πŸ§‘β€πŸ’» Development workflow + +[![Build](https://github.com/biopragmatics/curies.rs/actions/workflows/build.yml/badge.svg)](https://github.com/biopragmatics/curies.rs/actions/workflows/build.yml) [![Lint and Test](https://github.com/biopragmatics/curies.rs/actions/workflows/test.yml/badge.svg)](https://github.com/biopragmatics/curies.rs/actions/workflows/test.yml) [![codecov](https://codecov.io/gh/biopragmatics/curies.rs/graph/badge.svg?token=BF15PSO6GN)](https://codecov.io/gh/biopragmatics/curies.rs) [![dependency status](https://deps.rs/repo/github/biopragmatics/curies.rs/status.svg)](https://deps.rs/repo/github/biopragmatics/curies.rs) + +[Rust](https://www.rust-lang.org/tools/install), python, and NodeJS are required for development. + +Install development dependencies: + +```bash +# Activate python virtual env +python3 -m venv .venv +source .venv/bin/activate +# Install python dependencies +pip install maturin +# Install rust dev tools +rustup update +rustup component add rustfmt clippy +cargo install wasm-pack cargo-tarpaulin mdbook mdbook-admonish cargo-make +``` + +### πŸ“₯️ Clone the repository + +Clone the `curies.rs` repository, `cd` into it, and create a new branch for your contribution: + +```bash +cd curies.rs +git checkout -b add-my-contribution +``` + +### πŸ§ͺ Run tests + +Run tests for all packages: + +```bash +cargo test +``` + +Display prints: + +```bash +cargo test -- --nocapture +``` + +Run a specific test: + +```bash +cargo test new_empty_converter -- --nocapture +``` + +If tests panic without telling on which test it failed: + +```bash +cargo test -- --test-threads=1 +``` + +Test the `curies` crate with code coverage: + +```bash +cargo tarpaulin -p curies --out html +``` + +### 🐍 Run python + +Build the pip package, and run the `python/try.py` script: + +```bash +./scripts/build-python.sh +``` + +Or just run the script: + +```bash +source .venv/bin/activate +python python/try.py +``` + +### 🟨 Run JavaScript + +Build the npm package: + +```bash +./scripts/build-js.py +``` + +Start a web server: + +```bash +python -m http.server 3000 --directory ./js +``` + +Open [localhost:3000](http://localhost:3000) in your web browser. + +### ✨ Format + +```bash +cargo fmt +``` + +### 🧹 Lint + +```bash +cargo clippy --all --all-targets --all-features +``` + +### πŸ“– Generate docs locally + +Install dependencies: + +```bash +./scripts/docs-install.sh +``` + +Build and serve: + +```bash +./scripts/docs-serve.sh +``` + +### 🏷️ New release + +Publishing artifacts will be done by the `build.yml` workflow, make sure you have set the following tokens as secrets for this repository: `PYPI_TOKEN`, `NPM_TOKEN`, `CRATES_IO_TOKEN`, `CODECOV_TOKEN` + +Install dependency: + +```bash +cargo install cargo-outdated +``` + +1. Make sure dependencies have been updated: + + ```bash + cargo update + cargo outdated + ``` + +2. Bump the version in the `Cargo.toml` file in folders `lib/`, `python`, `js` + + ```bash + ./scripts/bump.sh 0.0.2 + ``` + +3. Commit, push, and create a new release on GitHub + +4. The `build.yml` workflow will automatically build artifacts (binary, pip wheel, npm package), and add them to the new release. diff --git a/lib/docs/introduction.md b/lib/docs/introduction.md new file mode 100644 index 0000000..1c2189f --- /dev/null +++ b/lib/docs/introduction.md @@ -0,0 +1,41 @@ +# Introduction + +[![crates.io](https://img.shields.io/crates/v/curies.svg)](https://crates.io/crates/curies) +[![PyPI](https://img.shields.io/pypi/v/curies-rs)](https://pypi.org/project/curies-rs/) +[![npm](https://img.shields.io/npm/v/@biopragmatics/curies)](https://www.npmjs.com/package/@biopragmatics/curies) + +A cross-platform Rust library for idiomatic conversion between URIs and compact URIs (CURIEs). + +Whether you're a developer looking to work with CURIEs (e.g. expand or compress) in your application, or a researcher seeking an efficient way to handle CURIEs, `curies` offers a suite of tools tailored to meet your needs. + +## πŸ”‘ Key Features + +### ✨ CURIEs management + +- πŸ› οΈ **Create** your custom converter +- πŸ“₯ **Import** converters from JSON or JSON-LD context, with helper functions for popular converters, such as `get_obo_converter()`. +- πŸ”— **Expand**: CURIEs from their compressed form to a URI. +- πŸ—œοΈ **Compress** URIs to CURIEs. + +### πŸ“¦οΈ Packaged for multiple interfaces + +This library is packaged for easy use across various interfaces and languages: + +- πŸ¦€ **Rust developers**: available as a Rust crate `curies`. +- 🐍 **Python programmers**: available as a Python pip package `curies-rs`. +- 🌐 **Web developers**: available as a NPM package `@biopragmatics/curies`, compiled to [WebAssembly](https://webassembly.org/), for browser integrations with JavaScript, or NodeJS. + +### βš”οΈ Cross-platform support + +It runs seamlessly on: + +- 🐧 Linux +- 🍎 MacOS +- πŸͺŸ Windows +- 🦊 Web browsers + +## πŸš€ Getting started + +Checkout the page most adapted to your use-case to get started. + +> πŸ’‘ **Need Help or Have Suggestions?** We welcome your input and feedback! If you encounter any issues or have ideas to enhance this tool, please [create an issue](https://github.com/biopragmatics/curies.rs/issues) on our GitHub repository. diff --git a/lib/docs/use_javascript.md b/lib/docs/use_javascript.md new file mode 100644 index 0000000..077d5d4 --- /dev/null +++ b/lib/docs/use_javascript.md @@ -0,0 +1,125 @@ +# 🟨 Use from JavaScript + +[![npm](https://img.shields.io/npm/v/@biopragmatics/curies)](https://www.npmjs.com/package/@biopragmatics/curies) + +You can easily work with CURIEs from JavaScript, or TypeScript with the [`@biopragmatics/curies`](https://www.npmjs.com/package/@biopragmatics/curies) NPM package. + + +## πŸš€ Use it in bare HTML files + +You can easily import the NPM package from a CDN, and work with `curies` from a simple `index.html` file: + +```html + + + + + CURIEs example + + + +

+

+ + + + +``` + +Then just start the web server from the directory where the HTML file is with: + +```bash +npx http-server +# Or: +python -m http.server +``` + +## πŸ“₯️ Install + +Install the `npm` package (use `yarn` or `pnpm` if you prefer) to use it from your favorite framework: + +```bash +npm install @biopragmatics/curies +``` + +## βš›οΈ Use from any JavaScript framework + +It can be used from any JavaScript framework, or NodeJS. + +For example, to use it in a nextjs react app: + +1. Create the project and `cd` into your new app folder + + ```bash + npx create-next-app@latest --typescript + ``` + +2. Add the `@biopragmatics/curies` dependency to your project: + + ```bash + npm install --save @biopragmatics/curies + ``` + +3. Add code, e.g. in `src/app/page.tsx`: + + ```typescript + 'use client' + import { useEffect, useState } from 'react'; + import init, { Converter, Record } from "@biopragmatics/curies"; + + export default function Home() { + const [output, setOutput] = useState(''); + useEffect(() => { + + // Initialize the wasm library and use it + init().then(async () => { + const rec1 = new Record("obo", "http://purl.obolibrary.org/obo/", [], []); + console.log(rec1.toString()); + console.log(rec1.toJs()); + + // Populate the Converter with records, or import existing converters: + const converter = new Converter(); + converter.addRecord(rec1); + console.log(converter.toString()) + + const compressedUri = converter.compress("http://purl.obolibrary.org/obo/DOID_1234"); + const expandedUri = converter.expand("DOID:1234"); + setOutput(compressedUri); + }); + }, []); + + return ( +
+

{output}

+
+ ); + } + ``` + +4. Start in dev: + + ```bash + npm run dev + ``` diff --git a/lib/docs/use_python.md b/lib/docs/use_python.md new file mode 100644 index 0000000..950340a --- /dev/null +++ b/lib/docs/use_python.md @@ -0,0 +1,42 @@ +# 🐍 Use from Python + +[![PyPI](https://img.shields.io/pypi/v/curies-rs)](https://pypi.org/project/curies-rs/) + +You can easily work with `curies` from Python. + +```admonish warn title="Work in progress" +This package is a work in progress. +``` + +## πŸ“₯️ Install + +Install the `pip` package: + +```bash +pip install curies-rs +``` + +## πŸš€ Use + +Create a `Converter`, and expand/compress: + +```python +from curies_rs import Record, Converter + +rec1 = Record("doid", "http://purl.obolibrary.org/obo/DOID_", [], []) + +converter = Converter() +converter.add_record(rec1) + +uri = converter.compress("http://purl.obolibrary.org/obo/DOID_1234") + +print(uri) + +print(rec1.dict()) +``` + +Run the script: + +```bash +python curies.py +``` diff --git a/lib/docs/use_rust.md b/lib/docs/use_rust.md new file mode 100644 index 0000000..537735c --- /dev/null +++ b/lib/docs/use_rust.md @@ -0,0 +1,33 @@ +# πŸ¦€ Use from Rust + +[![crates.io](https://img.shields.io/crates/v/curies.svg)](https://crates.io/crates/curies) + +You can use the Rust crate to work with CURIEs: + +```rust +fn main() -> Result<(), Box> { + let mut converter = Converter::new(); + + let record1 = Record { + prefix: "doid".to_string(), + uri_prefix: "http://purl.obolibrary.org/obo/DOID_".to_string(), + prefix_synonyms: HashSet::from(["DOID".to_string()]), + uri_prefix_synonyms: HashSet::from(["https://identifiers.org/DOID/"].map(String::from)), + }; + let record2 = Record::new("obo", "http://purl.obolibrary.org/obo/"); + converter.add_record(record1)?; + converter.add_record(record2)?; + + let uri = converter.expand("doid:1234")?; + println!("Expanded CURIE: {}", uri); + + let curie = converter.compress("http://purl.obolibrary.org/obo/DOID_1234")?; + println!("Compressed URI: {}", curie); + Ok(()) +} +main() +``` + +## πŸ“– API reference + +Checkout the **[API documentation](https://docs.rs/curies)** for more details on how to use the different components and functions of the rust crate. diff --git a/lib/src/lib.rs b/lib/src/lib.rs index affdba6..da2d2a6 100644 --- a/lib/src/lib.rs +++ b/lib/src/lib.rs @@ -1,3 +1,4 @@ +#![doc = include_str!("../docs/use_rust.md")] use async_trait::async_trait; use error::CuriesError; use serde::{Deserialize, Serialize}; diff --git a/scripts/build-js.sh b/scripts/build-js.sh new file mode 100755 index 0000000..3be60bb --- /dev/null +++ b/scripts/build-js.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash +set -e + +cd js + +npm run build + +python3 -m http.server +# Or npm run start diff --git a/scripts/build-python.sh b/scripts/build-python.sh new file mode 100755 index 0000000..ff98433 --- /dev/null +++ b/scripts/build-python.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash +set -e + +source .venv/bin/activate +cd python + +maturin develop + +python try.py diff --git a/scripts/bump.sh b/scripts/bump.sh new file mode 100755 index 0000000..d6b21c1 --- /dev/null +++ b/scripts/bump.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash +set -e + +# Check if version argument is provided +if [ "$#" -ne 1 ]; then + echo "Usage: $0 " + exit 1 +fi + +new_version=$1 +files=( + "lib/Cargo.toml" + "cli/Cargo.toml" + "python/Cargo.toml" + "js/Cargo.toml" +) + +sed -i "s/^version = \"[0-9]*\.[0-9]*\.[0-9]*\"\$/version = \"$new_version\"/" "Cargo.toml" + +for file in "${files[@]}"; do + if [ -f "$file" ]; then + sed -i "s/curies = { version = \"[0-9]*\.[0-9]*\.[0-9]*\"/curies = { version = \"$new_version\"/" "$file" + echo "🏷️ Updated version in $file" + else + echo "⚠️ File not found: $file" + fi +done + +gmsg "🏷️ Bump to $new_version" || true diff --git a/scripts/cov.sh b/scripts/cov.sh new file mode 100755 index 0000000..c5dfb68 --- /dev/null +++ b/scripts/cov.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash +set -e + +cargo tarpaulin -p curies --out html --out xml --timeout 120 \ + --exclude-files lib/src/error.rs + +python -m http.server 3000 --directory . diff --git a/scripts/docs-build.sh b/scripts/docs-build.sh new file mode 100755 index 0000000..3acd59e --- /dev/null +++ b/scripts/docs-build.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash +set -e + +rm -rf target/doc + +mdbook build + +cargo doc --workspace --no-deps --exclude curies-js --exclude curies-py --target-dir target/doc + +echo "Docs generated in the target/doc folder" + +# rustdoc --extend-css custom.css src/lib.rs +# rustdoc --theme awesome.css src/lib.rs +# https://github.com/rust-lang/rust/blob/master/src/librustdoc/html/static/css/themes/ayu.css diff --git a/scripts/docs-install.sh b/scripts/docs-install.sh new file mode 100755 index 0000000..dc6579c --- /dev/null +++ b/scripts/docs-install.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash +set -e +# Script to install dependencies for development and enable pre-commit hooks + +rustup update + +cargo install mdbook mdbook-admonish mdbook-pagetoc + +mkdir -p theme +wget -O theme/mdbook-admonish.css https://raw.githubusercontent.com/leptos-rs/leptos/a8e25af5233bb014d3cee85e4e9be8b3e4586de9/docs/book/mdbook-admonish.css \ No newline at end of file diff --git a/scripts/docs-serve.sh b/scripts/docs-serve.sh new file mode 100755 index 0000000..37c4584 --- /dev/null +++ b/scripts/docs-serve.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash +set -e + +source scripts/docs-build.sh + +echo "πŸ¦€ Rust doc at http://0.0.0.0:3000/doc/curies" +echo "πŸ“– MdBook at http://0.0.0.0:3000" + +python -m http.server 3000 --directory ./target/doc + +# python3 -m webbrowser ./target/doc/ diff --git a/scripts/install-dev.sh b/scripts/install-dev.sh new file mode 100755 index 0000000..a130e36 --- /dev/null +++ b/scripts/install-dev.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash +set -e +# Script to install dependencies for development and enable pre-commit hooks + +python3 -m venv .venv +source .venv/bin/activate + +pip install maturin pre-commit + +rustup update +rustup component add rustfmt clippy + +cargo install wasm-pack cargo-tarpaulin cargo-make + +source scripts/docs-install.sh + +pre-commit install