This post introduces how mdoc evaluates Scala code examples with good
performance while reporting clear error messages. mdoc is a markdown
documentation tool inspired by tut.
Like tut, mdoc reads markdown files as input and produces markdown files as
output with the Scala code examples evaluated. Unlike tut, mdoc does not use the
Scala REPL to evaluate Scala code examples. Instead, mdoc translates each
markdown file into a regular Scala program that evaluates in one run. In this
post, we look into the implications of this change and how it can deliver up to
27x faster performance when processing invalid documents.
The new compile-only modifier makes it possible to validate that a
code-example compiles successfully without evaluating the program at runtime.
This feature can be useful to demonstrate code that performs side-effects
val name = scala.io.StdIn.readLine("Please enter your name: ")
The compile-only modifier works for both for JVM and Scala.js code blocks.
You can now write mdoc:js code fences that compile with Scala.js and evaluate
as JavaScript in the browser. This features is great for Scala.js libraries to
write interactive documentation. To learn more, see the
documentation.
No spurious -Ywarn-discard-value warnings
He mdoc generated code previously reported a warning when compiled with the
-Ywarn-discard-value option. Now, the generated code no longer reports
warnings.
Clearer error messages for generated code
Previously, errors in generated mdoc code only reported the message without a
position making it difficult to track down the problem. Now, errors in generated
code show the generated code making it easier to see what's going on.
It is no longer possible to make --out a subdirectory of --in to prevent the
number of files for mdoc to process to grow exponentially. Previously, this
situation could silently happen with mis-configuration in the build but now mdoc
fails fast when it happens.
Build sbt-mdoc against sbt 1.0.0
The sbt-mdoc plugin is now compiled against sbt 1.0.0 to avoid binary
compatibility issues.
Scala 2.12 introduced a regression that caused asynchronous code to hang
forever in object constructors, see
scala-dev/#195.
This caused mdoc issues like
#124, where futures would
timeout. To workaround this problem, mdoc now uses the compiler option
-Ydelambdafy:inline by default.
New --no-link-hygiene option
Use the command-line argument --no-link-hygiene to disable link hygiene so that warnings are not reported. With sbt-mdoc, add
mdocExtraArguments := List("--no-link-hygiene")
Markdown footnotes now work
Previously, markdown footnotes would render incorrectly, which has now been fixed so it's possible to write like below.
Paragraph with a footnote reference[^1]
[^1]: Footnote text added at the bottom of the document
Improved stack traces
Previously, exceptions with causes were printed with full stack traces. Now, all exception stacktraces are trimmed to only show relevant parts.
It's now possible to declare sealed ADTs like below without getting a warning warning: The outer reference in this type test cannot be checked at run time..
sealedabstractclassMaybe[+A] extendsProductwithSerializablefinalcaseclassJust[A](value: A) extendsMaybe[A]finalcaseobjectNothingextendsMaybe[Nothing]
The error happened because we wrapped the code in class Session { class App { ... } }. Now, we wrap the code in object Session { object App { ... } }
instead, which removes the warning.
It's now possible to combine modifiers like reset:silent or reset:fail.
```scala mdoc
val x = 1
```
```scala mdoc:reset:fail
println(x)
```
This example produces the following output.
val x = 1// x: Int = 1
println(x)
// error: not found: value x// println(x)// ^
Relative filenames in :crash stacktraces
Previously, stack traces from :crash included absolute paths. Now they include only relative filenames.
// scala.MatchError: final val x = 2 (of class scala.meta.Defn$Val$DefnValImpl)
-// at repl.Session.$anonfun$app$47(/Users/ollie/dev/scalameta-tutorial/docs/trees/guide.md:252)+// at repl.Session.$anonfun$app$47(guide.md:252)
I am pleased to announce the release of mdoc v1.0.0. mdoc is a markdown
documentation tool for Scala inspired by tut.
New website
The mdoc readme has been replaced with this website and the documentation has
been expanded to cover mdoc features in more depth. There is a new
"Coming from tut" guide to help tut
users migrate to mdoc.
New sbt plugin
There is now an sbt-mdoc plugin that makes it easier to use mdoc from sbt
builds. See the
installation instructions
to learn how to use sbt-mdoc.
Docusaurus integration
The sbt-mdoc plugin includes a DocusaurusPlugin to integrate mdoc with
Docusaurus. Several projects already use mdoc in
combination with Docusaurus:
See the
docusaurus instructions
to learn how to use DocusaurusPlugin and configure CI to publish to GitHub
pages.
Improved :fail modifier
Previously, mdoc used Scala macros to implement the :fail modifier which
produces incorrect compilation errors in rare cases. See
#95. Now, mdoc translates each
:fail modifier into a standalone Scala program and compiles it with the Scala
compiler ensuring that compile errors are always accurate.
New :reset modifier
Now it's possible to clear all leading imports and declarations in the markdown
document with the
mdoc:reset modifier.
New organization
Previously, the mdoc repository lived in olafurpg/mdoc and was published under
com.geirsson. Now, mdoc lives in scalameta/mdoc and is published under
org.scalameta.