2020 年第一季度,产品从 DITA 迁移到 Markdown,这让我有幸在半年内熟悉了 DITA 和 Markdown 两种不同的写作方式,也熟悉了迁移过程的各个方面,总结了一些经验教训。产品第一季度 release 后,时间相对宽裕,我想记录下整个迁移过程中自己的所学所思,以后说不定会有用处。这篇文章我就单说 Markdown, 其它方面诸如 GitHub,我会在另一篇文章里详述。
Markdown Tips
1. Header organization has to be consecutive (H1 > H2 > H3), if you accidentally go from H1 # to H3 #, your code will be off.
2. If content, like a list, should be indented and be a subset of the preceding content, include the subset content on a new line and indent it by two spaces or one tab.
3. Use git pull often to minimize conflicts when you merge and to ensure that you have the latest content that someone else merged.
4. Use the Visual Studio Code preview to see your output. Also use the browser preview as a guide…not always 100% accurate, but usually a good way to see your errors.
5. After you prompt the user to run a command, be sure to start the codeblock in the a new line; press the space bar three times to help with the alignment of the codeblock.
6. Use anchors for long topics. Since we are getting away from rigid concepts, task, and references, you can have different kinds of content all in one topic. Sometimes the topics get long. Anchors are built much like links.
7. Use the back tick character for surrounding coding text. You can’t use an apostrophe (‘). Use ``` in a row to begin a codeblock and end it with another ```
Markdown limitations
1. As previously mentioned, to add a list to a table cell, create your .md table, then use HTML within a cell to create your list. This should be the only time you need to use HTML within a.md file.
2. Version control can be an issue since you do not have .ditavals. The simpler you keep the versioning, the better.
3. You need to know the Style Guide and stay on top of changes. Standardization is not as easy as it is in DITA. For instance, IBM DITA writers know exactly when to use ui-control (click something is bold), and when to use wintitle (window or page is italicized). This is because the DITA tag alone takes care of the text meaning for us. Work as a team to follow the style guide and use bold, italics, lists, etc.
Markdown 标签
刚开始不喜欢 Markdown, 觉得什么都要自己敲,没有 DITA 标签用的方便。对 Markdown 的用法熟记于心后,觉得敲就敲吧,也不费太多时间。但随之而来的产品文档格式不一致问题,更让人头疼。每个 information developer 都用自己的方式来完成一篇文章,看起来也遵循了格式规范,可是整个文档系统非常杂乱无章。举几个例子:
1. 代码块里的变量名,有人用 <install_dir>, 有人用 Install_dir。
2. 用户需要注意的点,有人用 **Note** 来加粗表示, 有人就用普通的 Note。
3. 有人用 html 格式的表格,有人用 Markdown 格式的表格。
在 产品 800 个 DITA 文档用 Pandoc 转换成 Markdown 格式后,文档里有大量的格式错误,也充斥着大量 html 标签,我们花了一段时间修改自己 own 的 文档,却没有提前就格式统一问题定好规则。这个问题导致后来又进行了新一轮的修改,费时费力。
以下是目前产品统一采用的规范:
1. 去掉所有不必要的 html 标签,比如 <table>, <span>, <img> <a href>. 全部使用 Markdown 格式。
例外:
- 允许使用 <br> 表示换行。
- Markdown 格式的 table 不支持 list. 尽量在 table 里不用 list。但必须用的情况下可以用 <ul> 和 <ol>。
2. 使用 #,## ,### 表示 headings, 而不用---。Use hash sign instead of dashes for headings.
示例:
# Heading 1
## Heading 2
3. 简化表格,去掉合并单元格,因为 Markdown 表格不支持。
4. 使用 space 表示空格。
5. Use <variable> in command and underneath use italic to describe variable.
示例:
Run the following command:
<install_dir>/bin/ececute.sh config <instance_name>
Where *install_dir* is the path where the agent is installed and *instance_name* is the name that you want to give to the agent instance.
需要注意的是:
如果你把<variable_name>放到 ``` 和 ``` 之间的 codeblock 里,或者 ` `之间用
monospace 表示,<variable_name> 能够正确显示。但如果你把<variable_name>放到
** 和 ** 之间来加粗显示,或者放到 * 和 * 之间来斜体显示, markdown preview 显示正常,发布后就惨了,<variable_name>消失了你都不知道,因为命令的其他部分仍然可以显示。用户运行这个命令失败,影响很大。
解决办法是用 <表示 <, 用 > 表示 >
6. 使用键盘上的 tab 键表示 tab。
7. 尽量去掉文档中的截图,因为产品更新太快,截图很有可能过时。
8. 使用 Acrolinx 检查所有文档,确保没有 grammer、wording、trademark 等错误。
9. 统一 Tips, Important, Notes 格式。
- If there is only one sentence for the note/tip/important, use **note** and put the text right after it in one paragraph/line. It will NOT cause accessibility violation or potential violation. For example:
**Important1:** All on same line, with no Enter. text text text text text text text text text text text text text text.
- If there are any lists under the note/tip/important, then it has to be in multiple lines. So use something like ### note, and then followed by the lists of text. But if there are more than 1 such header note, make sure the id is unique, for example, for note 1, we can say something like ### things to note:, for note 2, we can say something like ### note, to avoid duplicate ids.
10. 所有文档发布前统一用 Acrolinux 检查语法、拼写、标点、trademark、用法等错误并修改。
11. 使用 Markdown Attributes.
{:shortdesc: .shortdesc}
Shortdesc renders as a special class in the HTML for the 1st paragraph.
Yes, one of its main roles involves retrievability. It also has some
functional roles within KC, such as the sentence that appears with links
within search results, child\nested topics, etc.
{:screen: .screen}
比如在 linux command line 敲了很多命令,返回了一些结果,可以 copy 命令和结果到 文档中,用以下方式表示:
```
linux command and result
```
{:screen}
{:codeblock: .codeblock}
Markdown 的 codeblock 不带自动复制功能,使用 {:codeblock} 可以使代码块能一键复制。
示例:
```
code
```
{:codeblock}
{:child: .link .ulchildlink}
{:childlinks: .ullinks}
用来在超级主题中表示子主题。
示例:
- {: child} [Installing xxx](config_xxx_install.md)
- {: child} [Creating a xxx test](config_xxx_restapi.md)
{: childlinks}
Markdown 表格
Markdown 表格虽然方便,熟悉了写起来也快,但坑也多。这里我记录几个坑以及如何趟过去。
1. Markdown 用 | 符号来分割每个单元格。比如:
| Tables | Are | Cool |
| ----------|-----| ------|
| col 3 is | right-aligned | $1600 |
有时候单元格内容本身包含 |。比如单元格内容是:运行 kubectl get pods | grep ***。如就这么输入,肯定会导致表格显示出错。用 \| 的方式来表示 |,在 markdown preview 表格显示无误,但在实际发布后的文档后表格显示仍然有问题。正确的方式是用 | 的转义字符 ¦
2. 如果表格的最后一个单元格是空的,markdown preview 没问题,发布后会发现表格最后一个单元格消失了。解决办法是在最后一个空单元格加空格的转义字符  
3. 实在需要在表格里加列表,就用 <ul> 或 <ol>。
|Tasks|References|
|-----|----------|
|View applications across clusters on one console. |<ul><li>[Managing clusters on one console](managing_cluster_console.md)</li></ul>|
4. 表格后要添加标题。
示例:
{: caption="Table 1. Helm chart configuration parameters caption-side="top"}
5. 最坑的是,但凡 Markdown 表格前有缩进,整个表格即使在 markdown preview 能正常显示,发布后一团乱。做了很多试验和交流后,发现 Markdown 表格前不能缩进。
举个例子:
表格在某个步骤后:
3. Enter xxxx.
| Tables | Are | Cool |
| ----------|-----| ------|
按照 Markdown 的规矩,这个表格需要缩进,才能正确显示在步骤 3 下面。一缩进,表格一团乱。不缩进, 步骤4 显示成步骤 1 了,表格没有显示在步骤3 下面的正确位置。
解决办法是不要在步骤 3 下面放这个表格,直接放到文章最后,设置个锚点,直接 For more information, see [Table 1](#table1) 吧。这样就不会有显示问题了。
Markdown TOC (Content Of Table)
Markdown TOC 非常敏感,但凡有一点小错误,TOC 不会正常显示。常见错误就是格式错误. 刚开始有问题大家就一行行的查,最近找到了个 XML 检查工具 (https://onlinexmltools.com/validate-xml),能自动查出问题。
Markdown 文件复制问题
云产品文档里使用 YAML 文件比较多,Javascript 代码块也不少。从 DITA 自动转换成 Markdown 格式后,文件格式会比较乱。 YAML 对格式要求又很高,多一个空格都会出错。可以用自动检查工具代替肉眼检查。Javascript 代码块最好是格式化后再写入 codeblock 里。
YAML checker: https://onlineyamltools.com/validate-yaml
Javascript 格式化工具: https://tool.oschina.net/codeformat/js/
Markdown conref 文件
如何自动从 DITA conref 格式(xml)转化成 markdown conref 格式呢? 我写了一个 python 脚本,可以自动转化 xml 格式的 conref 到 markdown conref.
注意:
1. For conref.yml file, every space is meaningful. Even if there is only one space error, the whole conref.yml file couldn’t be used. Conref items couldn’t be showed well in documents. Please ensure all the items are strictly right in format.
2. You can only use one conref.md file. It’s not possible to conref content from one file to another.
3. You cannot use conrefs in your toc.xml file. This file is not run through the build in the same way that the other files are. It is assumed by the build that it has already been through the process to resolve the conrefs. Spell out the conrefs in this file only.
conrefs2.xml 如下:
<?xml version="1.0" encoding="utf-8" ?>
<!-- This is list of customers -->
<keywords>
<keyword id="term_dc_cloudresource1">Kubernetes dc</keyword>
<keyword id="term_dcs_cloud">Kubernetes dc</keyword>
</keywords>
Python 脚本如下:
#coding=utf-8
import xml.dom.minidom
dom = xml.dom.minidom.parse('C:\\Temp\\conrefs2.xml')
root = dom.documentElement
keywords = root.getElementsByTagName("keyword")
filename = "C:\\Temp\\keyword.txt"
for keyword in keywords:
print(keyword.getAttribute("id"))
try:
tm = keyword.getElementsByTagName("tm")[0]
if tm != 'null':
str=keyword.toxml()
print(str)
with open(filename, 'a') as file_object:
file_object.write(keyword.getAttribute("id"))
file_object.write(":\n ")
file_object.write(str.replace(tm.toxml(),tm.childNodes[0].data))
file_object.write("\n")
print(str)
except BaseException:
print(keyword.childNodes[0].data)
with open(filename, 'a') as file_object:
file_object.write(keyword.getAttribute("id"))
file_object.write(":\n ")
file_object.write(keyword.childNodes[0].data)
file_object.write("\n")
脚本运行结果:
自动生成 Markdown conref 到 keyword.txt 文件里。
示例:
cf:
Cloud Foundry
cf-deploy-tool:
Cloud Foundry deployment tool
cfee:
Cloud Foundry Enterprise Environment
如何使用 Markdown conref 文件里的 keyword:
{{site.data.keyword.xxx}}
示例:
It interates with {{site.data.keyword.cf}}
keyword 好处:
一次修改,到处使用。比如产品名变了,不用改动所有用到产品名的文档,只需要改动 conref 文件里的产品名对应的 keyword。