Making the switch to Semantic Versioning

by Dan Allen -

After years of talking about it, we’re finally ready to make the switch to Semantic Versioning in Asciidoctor. This switch will happen as part of the next major release for each participating project.

About Semantic Versioning

Semantic Versioning (or SemVer, for short) is a logical system for selecting version numbers based on a simple MAJOR.MINOR.PATCH sequence.

  • A MAJOR version is for introducing incompatible changes (large or small).

  • A MINOR version is for adding backward-compatible functionality.

  • A PATCH version is for making bug fixes (backward compatible, of course).

There’s also room for a prerelease version via build metadata. You can learn more at https://semver.org.

In our current system, patch releases are indistinguishable from major and minor releases and there’s only a single release line. Experience has taught us (the hard way) that this situation is neither clear or sustainable. For us, SemVer is about having better communication and room to grow. It’s a system based on shared expectations and trust. Although it may not be perfect, SemVer should help to understand what a version number entails and when to upgrade. We can’t expect it to prevent breaking something, but at least you’ll know when it might.

Versioning projects independently

Switching to SemVer also means that the Asciidoctor projects, namely Asciidoctor, AsciidoctorJ, and Asciidoctor.js, will be versioned independently. Other projects in the ecosystem will likely start versioning independently as well (in fact, some already have).

AsciidoctorJ and Asciidoctor.js have both reached a point where the projects are much more than a redistribution of the Asciidoctor RubyGem. They have their own API, extensions model, custom features, and platform integration. And that warrants having their own version line. An independent version line will also allow users to better understand what to expect in each release.

After speaking with Robert (AsciidoctorJ lead) and Guillaume (Asciidoctor.js lead), here’s the system we agreed on:

  • The core processors (Asciidoctor, AsciidoctorJ, and Asciidoctor.js) will move to SemVer starting with the 2.0.0 release. We plan for all three projects to make this major version shift at roughly the same time to minimize confusion.

  • If Asciidoctor.js or AsciidoctorJ need a change in Asciidoctor, they can force Asciidoctor to be released. This means Asciidoctor will need to be “release ready” at all times. A patch or minor release won’t need much discussion, but a major release will, of course.

  • We will not attempt to align the version numbers between the three projects after 2.0.0. Guillaume laid out a strong case that trying to align the version numbers would work against SemVer and thus result in the version numbers losing their meaning. This does introduce the complexity of having to document the version of Asciidoctor that Asciidoctor.js or AsciidoctorJ provides. However, both AsciidoctorJ and Asciidoctor.js provide an API for accessing the version of the underlying Asciidoctor release. The release number is also available via the asciidoctor-version document attribute.

We considered ways to lock Asciidoctor, AsciidoctorJ, and Asciidoctor.js to the same version while still adhering to SemVer. However, we reached the conclusion that doing that would only perpetuate the situation that’s caused the backup of releases we’ve seen. It’s best if the projects have the freedom to release when the time is right to release. And with three version number segments (MAJOR.MINOR.PATCH), we finally have enough space for those releases to happen!

Next steps

We’ll start by repackaging the Asciidoctor 1.5.8 release as 2.0.0, with some minor adjustments to drop unsupported versions of Ruby. AsciidoctorJ and Asciidoctor.js will then follow with their 2.0.0 releases. At that point, we’ll stick to versioning according to SemVer rules as outlined above.


Asciidoctor.js 1.5.0 released to Bower and npm!

by Guillaume Grossetie and Anthonny Quérouil -

The release train is on the move! Version 1.5.0 of Asciidoctor.js has been released and is now available in Bower and npm. This release is an important step toward making Asciidoctor.js widely available to the JavaScript ecosystem.

Bower and npm
Asciidoctor in JavaScript.
It was a dream.
Then it was a prototype.
Now, it’s the real deal.
What is Asciidoctor.js?

Asciidoctor.js is the official library for using Asciidoctor in JavaScript. It shares the same source code as Asciidoctor and is transcompiled to JavaScript using Opal. With Asciidoctor.js, you can convert AsciiDoc content or analyze the structure of a parsed AsciiDoc document from JavaScript.

When upgrading to Asciidoctor 1.5.0, please refer to the migration guide for details about how to migrate your content.

Release highlights

Asciidoctor.js is Asciidoctor

As mentioned in the release notes for Asciidoctor 1.5.0, we worked hard to align Asciidoctor.js (JavaScript) and Asciidoctor core (Ruby). That means you can expect Asciidoctor.js to parse and convert documents just like the original. Even includes work!

Getting certain features to work, like includes, requires special consideration because JavaScript is a different environment than Ruby and there are even key variations between JavaScript environments!

For example, reading an include file in Ruby is just a matter of using the normal Ruby IO API. In a browser environment, we have to use XMLHttpRequest (i.e., Ajax) as the IO API instead. If Asciidoctor.js is running on Node.js, we have to use the Node IO API, fs.readSync(), to make it work.

Rest assured we’re continuing to work on smoothing any differences to bring all the great features of Asciidoctor core to JavaScript.

Read on to learn how to get your hands on Asciidoctor.js!

Using Asciidoctor.js is easier than ever before

If you are a frontend or backend JavaScript developer, you’re only one command away from getting the latest version of Asciidoctor.js

Bower package

Installing Asciidoctor.js with Bower
$ bower install asciidoctor.js --save
The optional --save flag automatically adds the package to your project’s dependencies.

Once the package installed, you can add the following script tag to your HTML page:

<script src="bower_components/asciidoctor.js/dist/asciidoctor-all.min.js"></script>

The asciidoctor-all.min.js is a minified version and includes Asciidoctor core, extensions API and Opal.

Here is a simple example that converts AsciiDoc to HTML5 using the doctype: 'inline' option and showtitle attribute:

var asciidoc = "http://asciidoctor.org[*Asciidoctor*] " +
    "running on https://opalrb.com[_Opal_] " +
    "brings AsciiDoc to the browser!";
var options = Opal.hash2(['doctype', 'attributes'], {doctype: 'inline', attributes: ['showtitle']});
var html = Opal.Asciidoctor.$convert(asciidoc, options);
console.log(html);

See the Front-end development guide to learn more about the Bower package.

npm package

Installing Asciidoctor.js with npm
$ npm install asciidoctor.js --save
The optional --save flag automatically adds the package to your project’s dependencies.

Once the package is installed, the first thing to do is to load the asciidoctor.js module using require, then you’re ready to start using the API:

sample.js
var asciidoctor = require('asciidoctor.js')(); (1)
var opal = asciidoctor.Opal; (2)

var processor = null;
var useExtensions = true;

if (useExtensions) {
  processor = asciidoctor.Asciidoctor(true); (3)
}
else {
  processor = asciidoctor.Asciidoctor(); (4)
}

var content = "http://asciidoctor.org[*Asciidoctor*] " +
    "running on https://opalrb.com[_Opal_] " +
    "brings AsciiDoc to Node.js!";
var options = opal.hash2(
    ['doctype', 'attributes'],
    {doctype: 'inline', attributes: ['showtitle']});
var html = processor.$convert(content, options); (5)
console.log(html); (6)
1 Load the Asciidoctor.js library
2 Retrieve and alias the top-level Opal namespace
3 Instantiate Asciidoctor with extensions enabled
4 Instantiate Asciidoctor without extensions
5 Convert AsciiDoc content to HTML5 using Asciidoctor.js
6 Print the HTML5 output to the console

Save the file as sample.js and run it using the node command:

$ node sample.js

You should see the following output in your terminal:

<a href="http://asciidoctor.org"><strong>Asciidoctor</strong></a> running on <a href="https://opalrb.com"><em>Opal</em></a> brings AsciiDoc to Node.js!</p>
To be successful with Asciidoctor.js, it’s important to understand how to work with Ruby objects in the JavaScript environment. We recommend that you browse the Opal documentation to learn how method names are mapped and what data types it expects.

See the Back-end development guide to learn more about the npm package.

Asciidoctor.js is heating up on Node

Node.js is where the hottest JavaScript is happening and npm is the package manager that manages and distributes that hotness. We wanted Asciidoctor.js to be a part of this ecosystem. We also needed it there to start building tools. That’s why we took the first step of packaging Asciidoctor.js as an npm package…​in fact, several! Asciidoctor now has a new playground!

Here are the npm packages that are published:

asciidoctor.js

the main npm package for Asciidoctor.js

grunt-asciidoctor

an npm package for processing AsciiDoc source files in your Grunt project

Here’s how the community is playing with these packages already:

asciidoc-preview (Atom Editor)

A plugin for Atom that shows you a preview of your document while you type!

asciidoc-preview (Brackets Editor)

An extension for Brackets that shows you a preview of your document while you type!

grunt-asciidoctor-assemble

a static website generator for Grunt by @tedbergeron

Of course there are still challenges, but we’ll solve them. Head over to the Asciidoctor.js project to get involved.

Let us play this new game!

Asciidoctor.js on the JVM

You read that right. The browser ain’t the only JavaScript game in town. (And we’re not talking about JavaScript engines that have escaped from the browser, like Node.js.) We’re talking about the most polyglot of polyglot runtimes, the JVM.

Alex Soto is working at getting Asciidoctor.js integrated into AsciidoctorJ so you can use it on the JVM using Nashorn, dynjs and other JavaScript engines that run on it. The AsciidocFX project is already using Asciidoctor.js on Nashorn, so it’s more than just an idea!

There are still several challenges to tackle to ensure Asciidoctor.js runs smoothly on the JVM, such as getting includes working. Head over to the AsciidoctorJ project to get involved and help make it happen!

Acknowledgments

The alignment of Asciidoctor.js with Asciidoctor core was a major effort. It required input from a lot of people and they really pulled together to meet this challenge.

We want to especially thank the Opal developers, notably Adam Beynon, meh and Elia Schito, for making Asciidoctor.js happen. They were very responsive to our effort, making changes and fixes to Opal and generally providing input that allowed us to continuously move forward.

We also want to thank Anthonny Quérouil for crafting a Grunt build to compile, aggregate and compress Asciidoctor.js and for helping to get the artifacts published to Bower and npm.

Thanks to everyone who tested Asciidoctor.js, either directly or by using the tools. Your participation has helped Asciidoctor.js become the real deal!

If you have questions or feedback, we encourage you to participate in the discussion list. Talk to you there!


  • 1 of 1