Add Code Blocks
Code blocks in the Istio documentation are embedded preformatted block of
content. We use Hugo to build our website, and it uses the text
and
text_import
shortcodes to add code to a page.
Using this markup allows us to provide our readers with a better experience. The rendered code blocks can be easily copied, printed, or downloaded.
Use of these shortcodes is required for all content contributions. If your content doesn’t use the appropriate shortcodes, it won’t be merged until it does. This page contains several examples of embedded blocks and the formatting options available.
The most common example of code blocks are Command Line Interface (CLI) commands, for example:
{{< text bash >}}
$ echo "Hello"
{{< /text >}}
The shortcode requires you to start each CLI command with a $
and it renders the
content as follows:
$ echo "Hello"
You can have multiple commands in a code block, but the shortcode only recognizes a single output, for example:
{{< text bash >}}
$ echo "Hello" >file.txt
$ cat file.txt
Hello
{{< /text >}}
By default and given the set bash
attribute, the commands render using bash
syntax highlighting and the output renders as plain text, for example:
$ echo "Hello" >file.txt
$ cat file.txt
Hello
For readability, you can use \
to continue long commands on new lines, for example:
{{< text bash >}}
$ echo "Hello" \
>file.txt
$ echo "There" >>file.txt
$ cat file.txt
Hello
There
{{< /text >}}
Hugo renders the multi-line command without issue:
$ echo "Hello" \
>file.txt
$ echo "There" >>file.txt
$ cat file.txt
Hello
There
Your workloads can be coded in various programming languages. Therefore, we have implemented support for multiple combinations of syntax highlighting in code blocks.
Add syntax highlighting
Let’s start with the following “Hello World” example:
{{< text plain >}}
func HelloWorld() {
fmt.Println("Hello World")
}
{{< /text >}}
The plain
attribute renders the code without syntax highlighting:
func HelloWorld() {
fmt.Println("Hello World")
}
You can set the language of the code in the block to highlight its syntax. The
previous example set the syntax to plain
, and the rendered code block doesn’t
have any syntax highlighting. However, you can set the syntax to Go, for
example:
{{< text go >}}
func HelloWorld() {
fmt.Println("Hello World")
}
{{< /text >}}
Then, Hugo adds the appropriate highlighting:
func HelloWorld() {
fmt.Println("Hello World")
}
Supported syntax
Code blocks in Istio support the following languages with syntax highlighting:
plain
markdown
yaml
json
java
javascript
c
cpp
csharp
go
html
protobuf
perl
docker
bash
By default, the output of CLI commands is considered plain text and renders without syntax highlighting. If you need to add syntax highlighting to the output, you can specify the language in the shortcode. In Istio, the most common examples are YAML or JSON outputs, for example:
{{< text bash json >}}
$ kubectl -n istio-system logs $(kubectl -n istio-system get pods -l istio-mixer-type=telemetry -o jsonpath='{.items[0].metadata.name}') mixer | grep \"instance\":\"newlog.logentry.istio-system\"
{"level":"warn","ts":"2017-09-21T04:33:31.249Z","instance":"newlog.logentry.istio-system","destination":"details","latency":"6.848ms","responseCode":200,"responseSize":178,"source":"productpage","user":"unknown"}
{"level":"warn","ts":"2017-09-21T04:33:31.291Z","instance":"newlog.logentry.istio-system","destination":"ratings","latency":"6.753ms","responseCode":200,"responseSize":48,"source":"reviews","user":"unknown"}
{"level":"warn","ts":"2017-09-21T04:33:31.263Z","instance":"newlog.logentry.istio-system","destination":"reviews","latency":"39.848ms","responseCode":200,"responseSize":379,"source":"productpage","user":"unknown"}
{"level":"warn","ts":"2017-09-21T04:33:31.239Z","instance":"newlog.logentry.istio-system","destination":"productpage","latency":"67.675ms","responseCode":200,"responseSize":5599,"source":"ingress.istio-system.svc.cluster.local","user":"unknown"}
{"level":"warn","ts":"2017-09-21T04:33:31.233Z","instance":"newlog.logentry.istio-system","destination":"ingress.istio-system.svc.cluster.local","latency":"74.47ms","responseCode":200,"responseSize":5599,"source":"unknown","user":"unknown"}
{{< /text >}}
Renders the commands with bash syntax highlighting and the output with the appropriate JASON syntax highlighting.
$ kubectl -n istio-system logs $(kubectl -n istio-system get pods -l istio-mixer-type=telemetry -o jsonpath='{.items[0].metadata.name}') mixer | grep \"instance\":\"newlog.logentry.istio-system\"
{"level":"warn","ts":"2017-09-21T04:33:31.249Z","instance":"newlog.logentry.istio-system","destination":"details","latency":"6.848ms","responseCode":200,"responseSize":178,"source":"productpage","user":"unknown"}
{"level":"warn","ts":"2017-09-21T04:33:31.291Z","instance":"newlog.logentry.istio-system","destination":"ratings","latency":"6.753ms","responseCode":200,"responseSize":48,"source":"reviews","user":"unknown"}
{"level":"warn","ts":"2017-09-21T04:33:31.263Z","instance":"newlog.logentry.istio-system","destination":"reviews","latency":"39.848ms","responseCode":200,"responseSize":379,"source":"productpage","user":"unknown"}
{"level":"warn","ts":"2017-09-21T04:33:31.239Z","instance":"newlog.logentry.istio-system","destination":"productpage","latency":"67.675ms","responseCode":200,"responseSize":5599,"source":"ingress.istio-system.svc.cluster.local","user":"unknown"}
{"level":"warn","ts":"2017-09-21T04:33:31.233Z","instance":"newlog.logentry.istio-system","destination":"ingress.istio-system.svc.cluster.local","latency":"74.47ms","responseCode":200,"responseSize":5599,"source":"unknown","user":"unknown"}
Dynamically import code into your document
The previous examples show how to format the code in your document.
However, you can use the text_import
shortcode to import content or
code from a file too. The file can be stored in the documentation repository or
in an external source with Cross-Origin Resource Sharing (CORS) enabled.
Import code from a file in the istio.io
repository
Use the file
attribute to import content from a file in the Istio
documentation repository, for example:
{{< text_import file="test/snippet_example.txt" syntax="plain" >}}
The example above renders the content in the file as plain text:
BEFORE
# $snippet SNIP1
This is chunk 1
on two lines
# $endsnippet
# $snippet SNIP2
This is chunk 2
# $endsnippet
# $snippet SNIP3
This is chunk 3
# $endsnippet
AFTER
Set the language of the content through the syntax=
field to get the
appropriate syntax highlighting.
Import code from an external source through a URL
Similarly, you can dynamically import content from the Internet. Use the url
attribute to specify the source. The following example imports the same file, but
from a URL:
{{< text_import url="https://raw.githubusercontent.com/istio/istio.io/master/test/snippet_example.txt" syntax="plain" >}}
As you can see, the content is rendered in the same way as before:
If the file is from a different origin site, CORS should be enabled on that
site. Note the GitHub raw content site (raw.githubusercontent.com
) may be used
here.
Import a code snippet from a larger file
Sometimes, you don’t need the contents of the entire file. You can control which
parts of the content to render using named snippets. Tag the code you want
in the snippet with comments containing the $snippet SNIPPET_NAME
and
$endsnippet
tags. The content between the two tags represents the snippet. For
example, take the following file:
BEFORE
# $snippet SNIP1
This is chunk 1
on two lines
# $endsnippet
# $snippet SNIP2
This is chunk 2
# $endsnippet
# $snippet SNIP3
This is chunk 3
# $endsnippet
AFTER
The file has three separate snippets: SNIP1
, SNIP2
, and SNIP3
. The
convention is name snippets using all caps. To reference a specific snippet in
your document, set the value of the snippet
attribute in the shortcode to the
name of the snippet, for example:
{{< text_import file="test/snippet_example.txt" syntax="plain" snippet="SNIP1" >}}
The resulting code block only includes the code of the SNIP1
snippet:
This is chunk 1
on two lines
You can use the syntax
attribute of the text_import
shortcode to
specify the syntax of the snippet. For snippets containing CLI commands, you can
use the outputis
attribute to specify the output’s syntax.
Link to files in GitHub
Some code blocks need to reference files from Istio’s GitHub repository.
The most common example is referencing YAML configuration files. Instead of
copying the entire contents of the YAML file into your code block, you can
surround the relative path name of the file with @
symbols. This markup
renders the path should as a link to the file from the current release branch in
GitHub, for example:
{{< text bash >}}
$ kubectl apply -f @samples/bookinfo/networking/virtual-service-reviews-v3.yaml@
{{< /text >}}
The path renders as a link that takes you to the corresponding file:
$ kubectl apply -f @samples/bookinfo/networking/virtual-service-reviews-v3.yaml@
By default, these links point to the current release branch of the istio/istio
repository. For the link to point to a different Istio repository
instead, you can use the repo
attribute, for example:
{{< text syntax="bash" repo="api" >}}
$ cat @README.md@
{{< /text >}}
The path renders as a link to the README.md
file of the istio/api
repository:
$ cat @README.md@
Sometimes, your code block uses @
for something else. You can turn the link
expansion on and off with the expandlinks
attribute, for example:
{{< text syntax="bash" expandlinks="false" >}}
$ kubectl apply -f @samples/bookinfo/networking/virtual-service-reviews-v3.yaml@
{{< /text >}}
Advanced features
To use the more advanced features for preformatted content which are described
in the following sections, use the extended form of the text
sequence
rather than the simplified form shown so far. The expanded form uses normal HTML
attributes:
{{< text syntax="bash" outputis="json" >}}
$ kubectl -n istio-system logs $(kubectl -n istio-system get pods -l istio-mixer-type=telemetry -o jsonpath='{.items[0].metadata.name}') mixer | grep \"instance\":\"newlog.logentry.istio-system\"
{"level":"warn","ts":"2017-09-21T04:33:31.249Z","instance":"newlog.logentry.istio-system","destination":"details","latency":"6.848ms","responseCode":200,"responseSize":178,"source":"productpage","user":"unknown"}
{"level":"warn","ts":"2017-09-21T04:33:31.291Z","instance":"newlog.logentry.istio-system","destination":"ratings","latency":"6.753ms","responseCode":200,"responseSize":48,"source":"reviews","user":"unknown"}
{"level":"warn","ts":"2017-09-21T04:33:31.263Z","instance":"newlog.logentry.istio-system","destination":"reviews","latency":"39.848ms","responseCode":200,"responseSize":379,"source":"productpage","user":"unknown"}
{"level":"warn","ts":"2017-09-21T04:33:31.239Z","instance":"newlog.logentry.istio-system","destination":"productpage","latency":"67.675ms","responseCode":200,"responseSize":5599,"source":"ingress.istio-system.svc.cluster.local","user":"unknown"}
{"level":"warn","ts":"2017-09-21T04:33:31.233Z","instance":"newlog.logentry.istio-system","destination":"ingress.istio-system.svc.cluster.local","latency":"74.47ms","responseCode":200,"responseSize":5599,"source":"unknown","user":"unknown"}
{{< /text >}}
The available attributes are:
Attribute | Description |
---|---|
file | The path of a file to show in the preformatted block. |
url | The URL of a document to show in the preformatted block. |
syntax | The syntax of the preformatted block. |
outputis | When the syntax is bash , this specifies the command output’s syntax. |
downloadas | The default file name used when the user downloads the preformatted block. |
expandlinks | Whether or not to expand GitHub file references in the preformatted block. |
snippet | The name of the snippet of content to extract from the preformatted block. |
repo | The repository to use for GitHub links embedded in preformatted blocks. |
Download name
You can define the name used when someone chooses to download the code block
with the downloadas
attribute, for example:
{{< text syntax="go" downloadas="hello.go" >}}
func HelloWorld() {
fmt.Println("Hello World")
}
{{< /text >}}
If you don’t specify a download name, Hugo derives one automatically based on one of the following available possible names:
- The title of the current page for inline content
- The name of the file containing the imported code
- The URL of the source of the imported code