When writing instructional text, authors often need to show before/after states of small code blocks. This is useful with purely additive modifications:
But it’s especially important to illustrate changed or deleted lines of code:
print("Goodbye") print("Cruel") print("World")
In that case, the author has several unsavory options:
- Provide a code block illustrating the final state of the code, along with a description of what the user needs to do to arrive there, e.g. “On line 1, replace
"Goodbye", and before line 2, insert the new line
- Provide two code blocks illustrating the state of code before and after the changes, as shown above.
- Use standard syntax for illustrating diffs with “+” and “-” characters in the first column of added and deleted lines, respectively. This unifies the listing, but doesn’t provide any visual indicator aside from the leftmost character.
DocC Tutorials already handle line-highlighed diffs of source code, but the capability doesn’t extend to articles. Even if an article’s primary purpose is not to provide a long-form step-by-step coding walkthrough, code diffs are extremely helpful. For example, the author could note important API differences, or illustrate small refactoring tasks.
Provide a code diff syntax for fenced code blocks. The syntax adds the word
diff to the beginning fence of any code block, which instructs the DocC to parse the code for leading “+” and “-” characters and render those lines accordingly. A diff code fence can simply be
```diff, or be followed by a language specification, like this:
Using a language specification in addition to
diff allows for the possibility of keeping syntax highlighting within highlighted lines.
```diff swift print("Hello") +print("World") ```
Renders the second line as a code addition.
```diff swift -print("Hello") +print("Goodbye") +print("Cruel") print("World") ```
Could render two ways:
- As one deleted line and two added lines
- As one unified, changed line, with both “Hello” and “World” present and formatted to indicate deletion and addition, and one added line
We can follow the basic rules of the
git diff format, in which the first character indicates no change (space), an addition (+), or a deletion (-).
There’s some existing work in highlight.js that tackles this. Note that rendering the “unified” format in which sufficiently similar lines are diffed internally would require significant work beyond the simpler approach.
Instead of the
git diff format, which arguably requires more work when pasting code from source files, and when editing code blocks in Markdown source, we could use the following formatting rules.
- Unchanged lines are rendered as is; no extra leading characters are required.
- Any line beginning with one or more “+” characters, followed by one space or tab character, is considered an added line. The leading characters are deleted.
- Any line beginning with one or more “-” characters, followed by one space or tab character, is considered a deleted line. The leading characters are deleted.
Within a code block, the number of leading indicator characters must be consistent. In most circumstances, a single character suffices; however, some languages—notably ObjectiveC—already use leading “-” and “+” characters. For such languages, the use of multiple leading indicators is required to disambiguate. For example,
```diff objc - (void)instanceMethod:(NSInteger)x; -- - (void)aRemovedInstanceMethod:(NSInteger)x; + (void)classMethod:(NSString *)s; ++ + (void)anAddedClassMethod:(NSString *)s; ```
In the code above, lines 2 and 4 are parsed as removed and added, respectively.
Unfortunately this increases the complexity of the algorithm. It also removes the capability to simply paste the output of
git diff into code blocks.