Hacking
Short instructions that aim to help potential contributors.
Getting Started
Tool versions
The versions of Node.js and Ruby used to develop the project are pinned in the mise.toml file at the root of the repository.
The GitHub Actions workflows read the same file, so you get the same versions as the CI.
We recommend using mise to install and activate these versions. From the root of the repository, run:
$ mise install
If you manage your tools differently, make sure to use the versions declared in mise.toml.
Development workflow
-
Set up the Asciidoctor reveal.js plugin in development mode
-
Modify the converter, written in plain Ruby, in
lib/asciidoctor_revealjs/converter.rb
There is no build step: each AsciiDoc node is converted by a matching convert_<node> method.
-
Render slides with your changes using:
$ bundle exec asciidoctor-revealjs <source.adoc>
Each convert_<node> method runs in the context of the node being converted (self is the node), so you can call node methods and inspect them directly.
The Asciidoctor API documentation describes what is available on each node.
Manual Tests
In order to help troubleshoot issues and test syntax improvements, test/converter-testkit/fixtures/standalone/ holds minimalist, real AsciiDoc presentations.
You can convert them and load the result in a browser to check if asciidoctor-revealjs behaves as expected; see the "Custom tests" section further down.
$ bundle exec rake examples:convert
The converted .html files are written next to their .adoc source in test/converter-testkit/fixtures/standalone/, ready to open in a browser.
Asciidoctor API’s gotchas
Attribute inheritance
The attr and attr? methods inherit by default.
That means if they don’t find the attribute defined on the Node, they look on the document.
You only want to enable inheritance if you intend to allow an attribute of the same name to be controlled globally. That might be good for configuring transitions. For instance:
= My Slides
:transition-speed: fast
== First Slide
However, there may be attributes that you don’t want to inherit. If that’s the case, you generally use the form:
attr('name', nil, false)
The second parameter value is the default attribute value, which is nil by default.
Relevant documentation: www.rubydoc.info/github/asciidoctor/asciidoctor/Asciidoctor%2FAbstractNode%3Aattr
Merge / Review policy
Any non-trivial change should be integrated in main via a pull-request. This gives the community a chance to participate and helps write better code because it encourages people to review their own patches.
Pull requests should come from personal forks in order not to clutter the upstream repository.
Wait time
Once a pull request is submitted, let it sit for 24-48 hours for small changes. If you get positive feedback you can merge before the sitting time frame. If you don’t get feedback, just merge after the sitting time frame.
Larger changes should sit longer at around a week. Positive feedback or no feedback should be handled like for small changes.
Breaking changes should sit until a maintainer has reviewed and approved them.
Remember that this is a slower-moving project, since people are not designing slides every day.
Work-in-progress pull-requests
Letting the maintainers know that you are working on a feature or a fix is useful. Early communication often saves time-consuming mistakes or avoids duplicated effort. We encourage contributors to communicate with us early.
Branches on forks of this project are not very visible to maintainers as much as pull requests (PR). For this reason we recommend to open a draft PR to let everyone know that you are working on a specific topic. Now, instead of prepending “WIP”, we recommend using GitHub “draft pull request” feature instead.
Node package
Test locally
The converter is written natively in JavaScript (in js/src), so there is no build step.
In order to test the Node package, create a tarball of the project.
$ npm pack
That last command will produce a file named asciidoctor-reveal.js-<version>.tgz in the working directory.
Then, create a test project adjacent to the clone of the asciidoctor-reveal.js repository:
$ mkdir test-project $ cd test-project
Now, install the dependencies from the tarball:
$ npm i --save ../asciidoctor-reveal.js/asciidoctor-reveal.js-<version>.tgz
The relative portion of the last command is where you are installing the local asciidoctor-reveal.js version from.
|
Then proceed as documented in the README.adoc.
RubyGem package
Test a local asciidoctor-revealjs version
The converter is written in plain Ruby (in lib/asciidoctor_revealjs/converter.rb), so there is no build step.
In a clean directory besides the asciidoctor-reveal.js repository, create the following Gemfile file:
source 'https://rubygems.org'
gem 'asciidoctor-revealjs', :path => '../asciidoctor-reveal.js'
Then run:
$ bundle --path=.bundle/gems --binstubs=.bundle/.bin
Update dependencies
Update one dependency at a time by bumping its version manually, then install it and run the tests.
Avoid bundle update and npm update: they may upgrade many (transitive) dependencies at once, which makes regressions much harder to track down.
|
For a Ruby dependency, bump its version in asciidoctor-revealjs.gemspec (or in the Gemfile), then:
bundle install
bundle exec rubocop
bundle exec rake test
bundle exec rake examples:convert
For a JavaScript dependency, bump its version in package.json, then:
npm install
npm test
npm run examples
Release process
Prepare the release
-
Make sure that the changelog is up-to-date: all the entries for the upcoming release should be listed under the
## main (unreleased)section of CHANGELOG.mdYou can get the list of all contributors using
git(don’t forget to replace%prev-version-tag%with the previous tag name):$ git log %prev-version-tag%.. --format="%aN" --reverse | perl -e 'my %dedupe; while (<STDIN>) { print unless $dedupe{$_}++}' | sort -
Make sure that the highlight plugin code embed in lib/asciidoctor_revealjs/highlightjs.rb is up-to-date with the version of reveal.js
-
Make sure the changelog is committed and pushed to
main.
Release
The release is fully automated and triggered from GitHub Actions.
Both registries use trusted publishing (OIDC), so no API key or token needs to be configured:
publishing to rubygems.org relies on RubyGems trusted publishing
and publishing to npmjs.com relies on npm trusted publishers.
See the .github/workflows/release.yml file for details.
To trigger a release:
-
Go to the Release workflow on GitHub Actions.
-
Click Run workflow, keep the
mainbranch selected, and enter the version to release (e.g.,5.3.0or5.3.0-beta.1). -
Click Run workflow.
The workflow bumps the version in package.json and lib/asciidoctor_revealjs/version.rb, rolls the main (unreleased) changelog section into a dated %version% (%date%) section, and runs the tests.
Only if the tests pass does it commit, tag (v%version%) and push to main, then publish to rubygems.org and npmjs.com and build the single executable binaries (one per platform) attached to the GitHub release.
|
The |
Once the release workflow has been completed:
-
Check that the new version is available on rubygems.org
-
Check that the new version is available on npmjs.com
-
Check that a release has been created on GitHub.
In addition, you can submit pull requests to downstream project:
-
submit a pull request downstream to update Asciidoctor reveal.js version in the Asciidoctor Docker Container
-
modify the
Dockerfile,tests/asciidoctor.bats,README.mdandREADME.adocin: github.com/asciidoctor/docker-asciidoctor
-
-
submit a pull request downstream to update AsciidoctorJ reveal.js version
-
modify
gradle.propertiesandasciidoctorj-revealjs/gradle.properties. If the reveal.js version has been updated,
also amendWhenBackendIsRevealJs.javain bothtestsanditestsfolders andREADME.adocin: github.com/asciidoctor/asciidoctorj-reveal.js
-
Prepare next version
This step is optional, manual, and run locally — the next version isn’t always a minor bump (it could be a patch or a breaking major release), so it’s not computed automatically.
Pick the next -dev version (e.g., after releasing 5.3.0, that’s usually 5.4.0-dev, but use 5.3.1-dev or 6.0.0-dev if that fits better), then:
$ node tasks/version.js next <version> $ git commit -a -m "Begin development on next release <version>" $ git push origin main
This sets <version> in package.json and lib/asciidoctor_revealjs/version.rb, and its major.minor in docs/antora.yml.
Maintenance branch
You can (not must) create a maintenance branch from a tag, only when needed (e.g., to backport a fix to a previous line).
Name it {major}.{minor}.x, without a v prefix (e.g., 5.2.x): the release workflow only accepts main or a branch matching this pattern, and derives the npm dist-tag from it (latest-5-2 for 5.2.x).
-
create the branch from the release tag:
git checkout -b 5.2.x v5.2.0 -
push the maintenance branch:
git push origin 5.2.x -
don’t forget to update Antora playbook to add this branch: github.com/asciidoctor/docs.asciidoctor.org/edit/main/antora-playbook.yml
To release from a maintenance branch, select it instead of main when you run the release workflow.
New major version
In case of a new major version, you must follow the steps described for a Maintenance branch.
Ruby and asciidoc-converter-testkit tests
Running tests
We recommend tests to be run with a fresh installation of all dependencies in a local folder that won’t affect your Ruby install (a .bundle/ in this directory):
$ bundle --path=.bundle/gems --binstubs=.bundle/.bin
The fixture corpus runs through asciidoc-converter-testkit (the asciidoc-converter-testkit-cli npm package), so also install the JavaScript dependencies:
$ npm install
Then you can execute the full test suite (unit tests and the fixture corpus) with:
$ bundle exec rake test
bundle exec rake test:unit runs just the unit tests, skipping the fixture corpus — useful on JRuby/TruffleRuby, where the corpus’s hundreds of sequential bundle exec spawns turn a couple of minutes into ten or more.
Fixture corpus
rake testkit:test runs two invocations of asciidoc-converter-testkit against the Ruby converter, since a converter flag it needs differs between them (see tasks/testkit.rake for the detail):
-
the bundled 37 generic AsciiDoc-construct families (
test/converter-testkit/expected/generic/<family>/<case>.html), converted embedded; -
the project’s own
standalonefamily (test/converter-testkit/expected/standalone/<case>.html), converted standalone and narrowed to the relevant fragment via each case’s<name>.config.jsonselectsidecar.
Everything under test/converter-testkit/ belongs to the asciidoc-converter-testkit corpus: fixtures/ holds the input side (matching asciidoc-converter-testkit’s own --fixtures flag); expected/ holds the expected output — deliberately not also named "fixtures", to keep the two apart at a glance.
rake testkit:update regenerates the expected files from the current converter’s output — review the diff before committing.
Custom tests
Presentations in test/converter-testkit/fixtures/standalone/ double as a browsable gallery of real presentations and as regression tests. A file with no matching expected file under test/converter-testkit/expected/standalone/ is simply not (yet) covered by a regression test — that’s fine, it’s still a valid example.
The release notes showcase under release-notes/ (see below) is a separate, unrelated directory: it is not part of this test corpus at all.
Netlify Integration
On every commit or PR, the Netlify service will convert the release notes (release-notes/) into slides and host the resulting pages on its platform where it will be visible by anyone.
It hosts the converted HTML files, reveal.js framework and static content like images and CSS.
This integration will allow us to preview PRs and demo features to users (source and converted result).
See the release_notes:publish rake task in tasks/publish.rake and the netlify.toml configuration file.
Sensitive Data Accidentally Pushed Out
Only content that is copied into the public/ directory will be published on the Netlify site.
If, by accident, something sensitive is copied over there, delete it, rewrite the git history to remove the sensitive information and force push the branch.
Reach out to our Netlify integration contact to make sure that deployed branches were rebuilt and no longer contain the sensitive information.
Integration Contact
Main Contact: @ggrossetie
Also, in order to stay with a free plan, only the following people have control over our Netlify integration: @ggrossetie, @mojavelinux and @graphitefriction.