diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml
new file mode 100644
index 00000000..c0b774f4
--- /dev/null
+++ b/.github/workflows/documentation.yml
@@ -0,0 +1,70 @@
+name: Documentation
+
+on:
+ push:
+ branches: [master]
+ pull_request:
+ branches: [master]
+ workflow_dispatch:
+
+permissions:
+ contents: read
+
+concurrency:
+ group: documentation-${{ github.ref }}
+ cancel-in-progress: true
+
+jobs:
+ build:
+ name: Build user guide and API reference
+ runs-on: ubuntu-24.04
+ steps:
+ - name: Check out sources
+ uses: actions/checkout@v7
+
+ - name: Build existing Jekyll user guide
+ uses: actions/jekyll-build-pages@v1
+ with:
+ source: ./
+ destination: ./_site
+ baseurl: /${{ github.event.repository.name }}
+
+ - name: Install documentation tools
+ run: |
+ sudo apt-get update
+ sudo apt-get install --yes doxygen graphviz
+
+ - name: Build API reference
+ run: |
+ bash doc/build-api.sh "$RUNNER_TEMP/intarna-api"
+ # The Jekyll container creates its output as root.
+ sudo chown -R "$(id -u):$(id -g)" _site
+ cp -R "$RUNNER_TEMP/intarna-api/html" _site/api
+
+ - name: Check generated documentation
+ run: |
+ python3 doc/check-api.py _site/api
+ test -s _site/index.html
+ test -s _site/doc/figures/icon-up.28.png
+
+ - name: Upload documentation for review and deployment
+ uses: actions/upload-pages-artifact@v4
+ with:
+ path: _site
+ retention-days: 7
+
+ deploy:
+ name: Publish documentation
+ if: github.repository == 'BackofenLab/IntaRNA' && github.ref == 'refs/heads/master' && github.event_name != 'pull_request'
+ needs: build
+ runs-on: ubuntu-24.04
+ permissions:
+ pages: write
+ id-token: write
+ environment:
+ name: github-pages
+ url: ${{ steps.deployment.outputs.page_url }}
+ steps:
+ - name: Deploy GitHub Pages
+ id: deployment
+ uses: actions/deploy-pages@v4
diff --git a/ChangeLog b/ChangeLog
index 8c272627..de36b63d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -42,6 +42,9 @@
## Technical changes and Optimizations
+- add an API overview, IntaRNA Doxygen styling, and automated documentation
+ builds and GitHub Pages publishing alongside the user guide (issue #22)
+
- install personality links in out-of-tree builds, including IntaRNAsnap
- BUGFIX : normalize single-pair suboptimal boundaries before traceback and
@@ -126,6 +129,22 @@ energies, restricted partition sums, and trackers.
################################################################################
################################################################################
+261007 Alexander Mitrofanov
+ * doc/doxygen.cfg, doc/doxygen/* :
+ + introduce the API main page with component links, prediction flow,
+ coordinate/energy conventions, and library integration guidance
+ + add IntaRNA header/footer navigation and responsive project styling
+ * doc/build-api.sh, doc/check-api.py, doc/api-documentation.md, README.md :
+ + build HTML without C++ dependencies and check entry-page links/assets
+ + document local generation and the one-time Pages activation after merge
+ * .github/workflows/documentation.yml :
+ + build the existing Jekyll guide and API on PRs and master commits;
+ publish both together from master only, with API content under /api/
+ * Makefile.am, doc/Makefile.am :
+ * rebuild documentation when headers or documentation assets change and
+ include all documentation sources and build helpers in distributions
+ * addresses https://github.com/BackofenLab/IntaRNA/issues/22
+
261005 Alexander Mitrofanov
* bin/CommandLineParsing, tests/runKineticSeedExtension.sh :
+ add IntaRNAsnap personality with model=X, mode=K and outNoLP=true defaults;
diff --git a/Makefile.am b/Makefile.am
index d860ffdc..8d6de4cc 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -25,6 +25,11 @@ install-exec-hook:
if enable_doxygen
## doxygen documentation make target
@DX_RULES@
+
+# Refresh the API after changes to public headers, the overview, or branding.
+$(DX_DOCDIR)/$(PACKAGE).tag: $(wildcard $(srcdir)/src/IntaRNA/*.h) \
+ $(srcdir)/doc/doxygen/mainpage.md $(srcdir)/doc/doxygen/header.html \
+ $(srcdir)/doc/doxygen/footer.html $(srcdir)/doc/doxygen/intarna.css
else
## generate mandatory targets otherwise generated by doxygen.m4
DX_PHONY =
diff --git a/README.md b/README.md
index ed4cb9e3..7f8102ca 100644
--- a/README.md
+++ b/README.md
@@ -2378,6 +2378,14 @@ and functionalities used within the IntaRNA tool. The whole library comes with
an `IntaRNA` namespace and exhaustive class and member API documentation that is
processed using doxygen to generate html/pdf versions.
+Browse the [C++ API reference](https://backofenlab.github.io/IntaRNA/api/)
+for an overview of the library components and links to the class documentation.
+The online reference follows `master`. To generate it for your checkout, install
+Doxygen and Graphviz and run `bash doc/build-api.sh`, then open
+`doxygen-doc/html/index.html`. See the
+[API documentation build guide](doc/api-documentation.md) for validation,
+Autotools, and publishing instructions.
+
When IntaRNA is build while `pkg-config` is present, according pkg-config
information is generated and installed too.
diff --git a/doc/Makefile.am b/doc/Makefile.am
index c28d05ec..cb78b081 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -5,7 +5,14 @@
EXTRA_DIST = \
conda.txt \
+ api-documentation.md \
+ build-api.sh \
+ check-api.py \
doxygen.cfg \
+ doxygen/mainpage.md \
+ doxygen/header.html \
+ doxygen/footer.html \
+ doxygen/intarna.css \
latex-deps/adjcalc.sty \
latex-deps/adjustbox.sty \
latex-deps/collectbox.sty \
diff --git a/doc/api-documentation.md b/doc/api-documentation.md
new file mode 100644
index 00000000..e7382175
--- /dev/null
+++ b/doc/api-documentation.md
@@ -0,0 +1,65 @@
+# Building and publishing the API reference
+
+The API reference is generated from `src/IntaRNA/*.h` and
+`doc/doxygen/mainpage.md`. Its HTML header, footer, and extra stylesheet live in
+`doc/doxygen/`; the common configuration is `doc/doxygen.cfg`.
+
+## Local HTML build
+
+Install Doxygen and Graphviz (on Ubuntu: `sudo apt-get install doxygen graphviz`).
+The HTML templates are based on Doxygen 1.9.8, the version provided by the
+Ubuntu 24.04 CI runner. When updating Doxygen, compare them with freshly generated
+templates (`doxygen -w html header.html footer.html default.css`) and verify
+navigation and search before publishing.
+
+From the repository root:
+
+```bash
+bash doc/build-api.sh
+python3 doc/check-api.py doxygen-doc/html
+```
+
+Open `doxygen-doc/html/index.html`, or serve the directory with
+`python3 -m http.server --directory doxygen-doc/html` and browse
+`http://localhost:8000/`. An optional output directory can be passed to the build
+script; relative paths are resolved from the calling directory. The script only
+builds HTML and does not require a compiler, Boost, ViennaRNA, or an IntaRNA build.
+It uses the package version from `configure.ac`.
+
+In a configured Autotools checkout, the existing `make doxygen-doc` target uses
+the same content and styling. Configure with `--disable-doxygen-pdf` for an
+HTML-only build; PDF generation additionally requires the configured LaTeX tools.
+
+The link check verifies the entry page's local links (including class/member
+anchors), its styles and scripts, and the class/namespace/search entry points.
+Review Doxygen's warnings as well: existing header documentation can emit
+warnings, so the workflow does not treat every legacy documentation warning as
+fatal. New unresolved references should be fixed before merging.
+
+## GitHub Pages
+
+`.github/workflows/documentation.yml` builds documentation on pull requests to
+`master`, on pushes to `master`, and on manual dispatch. Every successful build
+uploads a `github-pages` artifact for review. Only a push or manual dispatch on
+`BackofenLab/IntaRNA`'s `master` can deploy; pull requests and forks cannot publish.
+The deployment job alone receives Pages and OIDC write permissions.
+
+The workflow first builds the existing README-based Jekyll site with its Slate
+theme, then adds Doxygen output under `api/`. It publishes both together:
+
+- User guide:
+- Development API:
+
+### One-time activation after merge
+
+The repository currently publishes from the root of the `master` branch. After
+merging the documentation workflow, a repository administrator must select
+**Settings → Pages → Build and deployment → Source → GitHub Actions**, then run
+the **Documentation** workflow on `master` (or push a subsequent commit).
+Retain any required approval rules on the `github-pages` environment. The PR
+does not change the live publishing settings. See GitHub's
+[custom Pages workflow documentation](https://docs.github.com/en/pages/getting-started-with-github-pages/using-custom-workflows-with-github-pages).
+
+No generated HTML, access token, or separate documentation branch is needed.
+Both the existing guide and the API are included in the deployment artifact;
+deploying only the API would replace the guide at the site's root.
diff --git a/doc/build-api.sh b/doc/build-api.sh
new file mode 100644
index 00000000..5ac932d8
--- /dev/null
+++ b/doc/build-api.sh
@@ -0,0 +1,35 @@
+#!/usr/bin/env bash
+# Build the HTML API without configuring or compiling the C++ library.
+set -euo pipefail
+
+if (( $# > 1 )); then
+ echo "Usage: $0 [output-directory]" >&2
+ exit 2
+fi
+
+source_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)"
+output_dir="${1:-$source_dir/doxygen-doc}"
+mkdir -p -- "$output_dir"
+output_dir="$(cd -- "$output_dir" && pwd)"
+cd -- "$source_dir"
+
+version="$(sed -n 's/^AC_INIT(\[IntaRNA\], \[\([^]]*\)\].*/\1/p' configure.ac)"
+test -n "$version"
+for tool in doxygen dot; do
+ if ! command -v "$tool" >/dev/null; then
+ echo "Missing documentation tool: $tool (install Doxygen and Graphviz)" >&2
+ exit 1
+ fi
+done
+dot_path="$(dirname -- "$(command -v dot)")"
+
+# These are the same substitutions provided by m4/doxygen.m4 for make doxygen-doc.
+env SRCDIR=. PROJECT=IntaRNA VERSION="$version" DOCDIR="$output_dir" \
+ GENERATE_HTML=YES GENERATE_LATEX=NO GENERATE_PDF=NO \
+ GENERATE_HTMLHELP=NO GENERATE_CHI=NO GENERATE_RTF=NO \
+ GENERATE_MAN=NO GENERATE_XML=NO PAPER_SIZE=a4 \
+ HAVE_DOT=YES DOT_PATH="$dot_path" \
+ doxygen doc/doxygen.cfg
+
+test -s "$output_dir/html/index.html"
+echo "API documentation: $output_dir/html/index.html"
diff --git a/doc/check-api.py b/doc/check-api.py
new file mode 100644
index 00000000..872fc8e8
--- /dev/null
+++ b/doc/check-api.py
@@ -0,0 +1,59 @@
+#!/usr/bin/env python3
+"""Check the generated API entry page, its links, and navigation assets."""
+
+import sys
+from html.parser import HTMLParser
+from pathlib import Path
+from urllib.parse import unquote, urlsplit
+
+
+class Page(HTMLParser):
+ def __init__(self, path):
+ super().__init__()
+ self.links = []
+ self.anchors = set()
+ self.feed(path.read_text(encoding="utf-8"))
+
+ def handle_starttag(self, tag, attrs):
+ attrs = dict(attrs)
+ for key in ("href", "src"):
+ if attrs.get(key):
+ self.links.append(attrs[key])
+ for key in ("id", "name"):
+ if attrs.get(key):
+ self.anchors.add(attrs[key])
+
+
+def check(directory):
+ for name in ("index.html", "annotated.html", "hierarchy.html",
+ "namespaceIntaRNA.html", "search/searchdata.js", "intarna.css"):
+ path = directory / name
+ if not path.is_file() or path.stat().st_size == 0:
+ raise ValueError(f"Missing or empty API output: {path}")
+
+ index = directory / "index.html"
+ page = Page(index)
+ pages = {index: page}
+ for link in page.links:
+ url = urlsplit(link)
+ if url.scheme or url.netloc:
+ continue
+ target = directory / unquote(url.path) if url.path else index
+ if not target.is_file():
+ raise ValueError(f"Broken API entry-page link: {link}")
+ if url.fragment and target.suffix == ".html":
+ if target not in pages:
+ pages[target] = Page(target)
+ if unquote(url.fragment) not in pages[target].anchors:
+ raise ValueError(f"Broken API entry-page anchor: {link}")
+
+ print(f"API entry page: {len(page.links)} links and assets checked")
+
+
+if __name__ == "__main__":
+ if len(sys.argv) != 2:
+ sys.exit("Usage: python3 doc/check-api.py ")
+ try:
+ check(Path(sys.argv[1]))
+ except (OSError, ValueError) as error:
+ sys.exit(str(error))
diff --git a/doc/doxygen.cfg b/doc/doxygen.cfg
index ad6439fd..a270e696 100644
--- a/doc/doxygen.cfg
+++ b/doc/doxygen.cfg
@@ -32,19 +32,19 @@ DOXYFILE_ENCODING = UTF-8
# title of most generated pages and in a few other places.
# The default value is: My Project.
-PROJECT_NAME = $(PROJECT)-$(VERSION)
+PROJECT_NAME = IntaRNA
# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
# could be handy for archiving the generated documentation or if some version
# control system is used.
-PROJECT_NUMBER =
+PROJECT_NUMBER = "$(VERSION)"
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
# quick idea about the purpose of the project. Keep the description short.
-PROJECT_BRIEF =
+PROJECT_BRIEF = "RNA-RNA interaction prediction | C++ API"
# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
# in the documentation. The maximum height of the logo should not exceed 55
@@ -58,7 +58,7 @@ PROJECT_LOGO =
# entered, it will be relative to the location where doxygen was started. If
# left blank the current directory will be used.
-OUTPUT_DIRECTORY = $(DOCDIR)
+OUTPUT_DIRECTORY = "$(DOCDIR)"
# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-
# directories (in 2 levels) under the output directory of each output format and
@@ -152,7 +152,7 @@ FULL_PATH_NAMES = YES
# will be relative from the directory where doxygen is started.
# This tag requires that the tag FULL_PATH_NAMES is set to YES.
-STRIP_FROM_PATH = $(SRCDIR)
+STRIP_FROM_PATH = "$(SRCDIR)"
# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
# path mentioned in the documentation of a class, which tells the reader which
@@ -758,7 +758,8 @@ WARN_LOGFILE =
# spaces.
# Note: If this tag is empty the current directory is searched.
-INPUT = $(SRCDIR)/src/IntaRNA
+INPUT = "$(SRCDIR)/src/IntaRNA" \
+ "$(SRCDIR)/doc/doxygen/mainpage.md"
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
@@ -778,7 +779,7 @@ INPUT_ENCODING = UTF-8
# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf,
# *.qsf, *.as and *.js.
-FILE_PATTERNS = *.h
+FILE_PATTERNS = *.h *.md
# The RECURSIVE tag can be used to specify whether or not subdirectories should
# be searched for input files as well.
@@ -894,7 +895,7 @@ FILTER_SOURCE_PATTERNS =
# (index.html). This can be useful if you have a project on for instance GitHub
# and want to reuse the introduction page also for the doxygen output.
-USE_MDFILE_AS_MAINPAGE =
+USE_MDFILE_AS_MAINPAGE = "$(SRCDIR)/doc/doxygen/mainpage.md"
#---------------------------------------------------------------------------
# Configuration options related to source browsing
@@ -1069,7 +1070,7 @@ HTML_FILE_EXTENSION = .html
# of the possible markers and block names see the documentation.
# This tag requires that the tag GENERATE_HTML is set to YES.
-HTML_HEADER =
+HTML_HEADER = "$(SRCDIR)/doc/doxygen/header.html"
# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
# generated HTML page. If the tag is left blank doxygen will generate a standard
@@ -1079,7 +1080,7 @@ HTML_HEADER =
# that doxygen normally uses.
# This tag requires that the tag GENERATE_HTML is set to YES.
-HTML_FOOTER =
+HTML_FOOTER = "$(SRCDIR)/doc/doxygen/footer.html"
# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
# sheet that is used by each HTML page. It can be used to fine-tune the look of
@@ -1104,7 +1105,7 @@ HTML_STYLESHEET =
# list). For an example see the documentation.
# This tag requires that the tag GENERATE_HTML is set to YES.
-HTML_EXTRA_STYLESHEET =
+HTML_EXTRA_STYLESHEET = "$(SRCDIR)/doc/doxygen/intarna.css"
# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
# other source files which should be copied to the HTML output directory. Note
@@ -1125,7 +1126,7 @@ HTML_EXTRA_FILES =
# Minimum value: 0, maximum value: 359, default value: 220.
# This tag requires that the tag GENERATE_HTML is set to YES.
-HTML_COLORSTYLE_HUE = 220
+HTML_COLORSTYLE_HUE = 175
# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
# in the HTML output. For a value of 0 the output will use grayscales only. A
@@ -1152,7 +1153,7 @@ HTML_COLORSTYLE_GAMMA = 80
# The default value is: YES.
# This tag requires that the tag GENERATE_HTML is set to YES.
-HTML_TIMESTAMP = YES
+HTML_TIMESTAMP = NO
# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
# documentation will contain sections that can be hidden and shown after the
@@ -2043,7 +2044,7 @@ TAGFILES =
# tag file that is based on the input files it reads. See section "Linking to
# external documentation" for more information about the usage of tag files.
-GENERATE_TAGFILE = $(DOCDIR)/$(PROJECT).tag
+GENERATE_TAGFILE = "$(DOCDIR)/$(PROJECT).tag"
# If the ALLEXTERNALS tag is set to YES, all external class will be listed in
# the class index. If set to NO, only the inherited external classes will be
@@ -2288,7 +2289,7 @@ INTERACTIVE_SVG = NO
# found. If left blank, it is assumed the dot tool can be found in the path.
# This tag requires that the tag HAVE_DOT is set to YES.
-DOT_PATH = $(DOT_PATH)
+DOT_PATH = "$(DOT_PATH)"
# The DOTFILE_DIRS tag can be used to specify one or more directories that
# contain dot files that are included in the documentation (see the \dotfile
diff --git a/doc/doxygen/footer.html b/doc/doxygen/footer.html
new file mode 100644
index 00000000..cff4d7c2
--- /dev/null
+++ b/doc/doxygen/footer.html
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+