Skip to content

Commit 035092c

Browse files
DOC-5804 first attempt at making specification doc for TCEs
1 parent 99fff14 commit 035092c

File tree

2 files changed

+1485
-0
lines changed

2 files changed

+1485
-0
lines changed

build/tcedocs/README.md

Lines changed: 239 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,239 @@
1+
# How to add a multi-language code examples to redis.io
2+
3+
## Configure Hugo
4+
5+
The website redis.io is built from Markdown files using [Hugo](https://gohugo.io). Multi-language code example support is configured in Hugo by adding information to its configuration file, `config.toml`.
6+
There are two sections that need to updated when new languages are added.
7+
8+
1. In the `[params]` section:
9+
10+
```toml
11+
clientsExamples = ["Python", "Node.js", "Java-Sync", "Java-Async", "Java-Reactive", "Go", "C#", "RedisVL", "PHP"]
12+
```
13+
14+
The order of the `clientsExamples` list matters: it's the order in which the language tabs are presented for each code example.
15+
1. In the `[params.clientsConfig]` section:
16+
17+
```toml
18+
[params.clientsConfig]
19+
"Python"={quickstartSlug="redis-py"}
20+
"Node.js"={quickstartSlug="nodejs"}
21+
"Java-sync"={quickstartSlug="jedis"}
22+
"Java-async"={quickstartSlug="lettuce"}
23+
"Java-reactive"={quickstartSlug="lettuce"}
24+
"Go"={quickstartSlug="go"}
25+
"C#"={quickstartSlug="dotnet"}
26+
"RedisVL"={quickstartSlug="redis-vl"}
27+
"PHP"={quickstartSlug="php"}
28+
```
29+
30+
This configuration, along with the configuration steps below, is used to control the behavior of the Hugo shortcode that was developed to show tabbed code examples.
31+
A shortcode is a simple snippet inside a content file that Hugo will render using a predefined template. This template can contain HTML and JavaScript.
32+
33+
### How to add a new programming language
34+
35+
#### Add the components file
36+
37+
The folder `data/components` contains one component configuration file for each supported language. These files contain information about the GitHub repos that house the code examples.
38+
39+
Here is the configuration file for Python, `redis_py.json`:
40+
41+
```json
42+
{
43+
"id": "redis_py",
44+
"type": "client",
45+
"name": "redis-py",
46+
"language": "Python",
47+
"label": "Python",
48+
"repository": {
49+
"git_uri": "https://github.com/redis/redis-py"
50+
},
51+
"examples": {
52+
"git_uri": "https://github.com/redis/redis-py",
53+
"path": "doctests",
54+
"pattern": "*.py"
55+
}
56+
}
57+
```
58+
59+
The `language` property needs to match the value that was added to the `config.toml` file in the previous step. The `label` property, while generally the same as `language`, may be set to a string that is different from `language`. For RedisVL, `language` is set to `Python` and `label` is set to `RedisVL`. The `examples` property points to a GitHub repository, a path under which examples should be searched, and a file name pattern. The current logic will scan for examples that fulfill the filename pattern within the given path.
60+
61+
#### Register the component file
62+
63+
Register your component file by adding it to the `clients` array in the `index.json` file, which resides in the the same folder as the per-language JSON files. The entry should match the file name prefix and ID of the component.
64+
65+
Here is an example:
66+
```json
67+
"clients": [
68+
"nredisstack",
69+
"go_redis",
70+
"node_redis",
71+
"php",
72+
"redis_py",
73+
"jedis",
74+
"lettuce_async",
75+
"lettuce_reactive",
76+
"redis_vl"
77+
]
78+
```
79+
80+
Code examples are pulled from the GitHub repo for each supported language at docs site build time.
81+
82+
### Verify that your language is supported by the source code file parser
83+
84+
Component handling is implemented in `build/components/component.py`. The example file parser that is used by it is implemented inside `build/components/example.py`. Add any language-specific information you need to have the build code support your language's examples.
85+
86+
```python
87+
TEST_MARKER = {
88+
'java': '@Test',
89+
'java-sync': '@Test',
90+
'java-async': '@Test',
91+
'java-reactive': '@Test',
92+
'c#': r'\[Fact]|\[SkipIfRedis\(.*\)]'
93+
}
94+
PREFIXES = {
95+
'python': '#',
96+
'node.js': '//',
97+
'java': '//',
98+
'java-sync': '//',
99+
'java-async': '//',
100+
'java-reactive': '//',
101+
'go': '//',
102+
'c#': '//',
103+
'redisvl': '#',
104+
'php': '//'
105+
}
106+
```
107+
108+
The `TEST_MARKER` dictionary maps programming languages to test framework annotations, which allows the parser to filter such source code lines out. The `PREFIXES` dictionary maps each language to its comment prefix. Python, for example, uses a hashtag (`#`) to start a comment.
109+
110+
## Understand special comments in the example source code files
111+
112+
Each code example uses special comments, such as `HIDE_START` and `REMOVE_START`, to control how the examples are displayed. The following list gives an explanation:
113+
114+
- `EXAMPLE id`: Defines the identifier of the source code example file, where `id` is any common string (for example, `cmds_string`). IDs should only contain ASCII alphanumeric characters, underline characters (`_`), or hyphen characters (`-`). Do not use multibyte characters.
115+
- `HIDE_START`: Starts a code block that should be *hidden* when showing the example. This code block will only become visible if **unhide** (the eye button) is clicked.
116+
- `HIDE_END`: Marks the end a hidden code block.
117+
- `REMOVE_START`: Starts a code block that should be entirely removed when the example is processed by the build code. This is useful for removing lines of code that do not contribute to the example but are needed to embed the code into a proper test case or framework. Good examples of such code blocks are imports of external libraries or test assertions.
118+
- `REMOVE_END`: Marks the end of a code block that should be removed from the example.
119+
- `STEP_START step-name`: Starts a code block that represents a specific step in a set of examples.
120+
- `STEP_END`: Marks the end of a code block that represents a specific step in a set of examples.
121+
122+
## Add examples to the client library or to the local_examples directory
123+
124+
Examples are added to either a client repo, or, temporarily, to the `local_examples` directory in the `redis.io/docs` repo.
125+
126+
### Add examples to the client libraries
127+
128+
Add a source code file to an appropriate client repo. Consult the /data/components/<client-component>.json file for the location.
129+
130+
| Programming Language | GitHub Repo | Default directory |
131+
|----------------------|-----------------------------------------------------|---------------------------------------------------|
132+
| C# | [NRedisStack](https://github.com/redis/NRedisStack) | `tests/Doc` |
133+
| Go | [go-redis](https://github.com/redis/go-redis) | `doctests` |
134+
| Java | [jedis](https://github.com/redis/jedis) | `src/test/java/io/redis/examples` |
135+
| | [Lettuce](https://github.com/redis/lettuce) | `src/test/java/io/redis/examples/async` or |
136+
| | | `src/test/java/io/redis/examples/reactive` |
137+
| Node.js | [node-redis](https://github.com/redis/node-redis) | `doctests` |
138+
| PHP | [Predis](https://github.com/predis/predis) | Examples, for now, are stored in `local_examples` |
139+
| Python | [redis-py](https://github.com/redis/redis-py) | `doctests` |
140+
| | [RedisVL](https://github.com/redis/redis-vl-python) | `doctests` |
141+
142+
### Add examples to the local_examples directory
143+
144+
At times, it can take quite a while to get new or updated examples through the review process. To make the examples available immediately on the docs site, you can place examples temporarily in the `local_examples/client-specific` directory. The manner in which files are added isn't terribly important, as the build code will recursively walk the entire directory, so it will find examples in any directory under `local_examples`.
145+
146+
```
147+
local_examples
148+
├── client-specific
149+
│   ├── go
150+
│   │   ...
151+
│   ├── jedis
152+
│   │   ...
153+
│   ├── lettuce-async
154+
│   │   ...
155+
│   ├── lettuce-reactive
156+
│   │   ...
157+
│   ├── nodejs
158+
│   │   ...
159+
│   └── redis-py
160+
│   ...
161+
```
162+
163+
## Add your example to the content page
164+
165+
In order to add a multi-language code example to a content page, use the `clients-example` shortcode:
166+
167+
```
168+
{{< clients-example id ... />}}
169+
```
170+
171+
The ID is the same one you used with `EXAMPLE: id` in the first line of your code example.
172+
173+
### Named versus positional parameters
174+
175+
The `clients-example` shortcode supports both positional and named parameters. The lion's share of current examples use positional parameters, but, going forward, names parameters should be used.
176+
177+
Named parameters:
178+
179+
- set: Name of the example set (required)
180+
- step: Example step name (required)
181+
- lang_filter: Language filter (optional, default: "")
182+
- max_lines: Maximum number of lines shown by default (optional, default: 100)
183+
- dft_tab_name: Custom first tab name (optional, default: ">_ Redis CLI")
184+
- dft_tab_link_title: Custom first tab footer link title (optional)
185+
- dft_tab_url: Custom first tab footer link URL (optional)
186+
- show_footer: Show footer (optional, default: true)
187+
188+
Positional parameters (for backward compatibility):
189+
190+
- 0: example set name
191+
- 1: step name
192+
- 2: language filter
193+
- 3: max lines
194+
- 4: custom first tab name
195+
- 5: custom first tab footer link title
196+
- 6: custom first tab footer link URL
197+
198+
### Examples
199+
200+
When converting existing content with redis-cli examples to the new format, you can wrap the existing redis-cli example:
201+
202+
```
203+
{{< clients-example set="set_and_get" step="" >}}
204+
> set mykey somevalue
205+
OK
206+
> get mykey
207+
"somevalue"
208+
{{< /clients-example >}}
209+
```
210+
211+
If the redis-cli example is too long you can hide some lines by specifying the limit as the fourth argument:
212+
213+
```
214+
{{< clients-example set="set_and_get" step="" lang_filter="" max_lines="2" >}}
215+
> set mykey somevalue
216+
OK
217+
> get mykey <-- this line will be hidden
218+
"somevalue" <-- this line will be hidden
219+
{{< /clients-example >}}
220+
```
221+
222+
To refer to a particular step placed in between `STEP_START stepname` and `STEP_END` comments in the code example, you should use the second argument to define the name of the step:
223+
224+
```
225+
{{< clients-example set="id" step="stepname" />}}
226+
```
227+
228+
If you need to embed an example for a specific programming language, the third argument should be defined:
229+
230+
```
231+
{{< clients-example set="id" step="stepname" lang_filter="lang" />}}
232+
```
233+
234+
The following example shows the `connect` step of a Python example:
235+
236+
```
237+
{{< clients-example set="set_and_get" step="connect" lang_filter="Python" />}}
238+
```
239+
The programming language name should match the value in the Hugo configuration file.

0 commit comments

Comments
 (0)