2015-09-20 00:34:52 +06:00
|
|
|
|
# Mark
|
|
|
|
|
|
2020-12-04 00:31:44 +03:00
|
|
|
|
Mark — a tool for syncing your markdown documentation with Atlassian Confluence
|
2016-11-30 18:44:32 +07:00
|
|
|
|
pages.
|
|
|
|
|
|
2020-07-28 11:04:33 +03:00
|
|
|
|
Read the blog post discussing the tool — https://samizdat.dev/use-markdown-for-confluence/
|
|
|
|
|
|
2020-07-25 10:58:32 +03:00
|
|
|
|
This is very useful if you store documentation to your software in a Git
|
|
|
|
|
repository and don't want to do an extra job of updating Confluence page using
|
|
|
|
|
a tinymce wysiwyg enterprise core editor which always breaks everything.
|
2015-09-20 00:34:52 +06:00
|
|
|
|
|
2020-07-25 10:58:32 +03:00
|
|
|
|
Mark does the same but in a different way. Mark reads your markdown file, creates a Confluence page
|
|
|
|
|
if it's not found by its name, uploads attachments, translates Markdown into HTML and updates the
|
|
|
|
|
contents of the page via REST API. It's like you don't even need to create sections/pages in your
|
|
|
|
|
Confluence anymore, just use them in your Markdown documentation.
|
2016-10-25 17:23:28 +07:00
|
|
|
|
|
2020-07-25 10:58:32 +03:00
|
|
|
|
Mark uses an extended file format, which, still being valid markdown,
|
|
|
|
|
contains several HTML-ish metadata headers, which can be used to locate page inside
|
2016-10-25 17:23:28 +07:00
|
|
|
|
Confluence instance and update it accordingly.
|
|
|
|
|
|
2020-07-25 10:58:32 +03:00
|
|
|
|
File in the extended format should follow the specification:
|
2016-10-25 17:23:28 +07:00
|
|
|
|
```markdown
|
2019-05-01 16:58:28 +03:00
|
|
|
|
<!-- Space: <space key> -->
|
|
|
|
|
<!-- Parent: <parent 1> -->
|
|
|
|
|
<!-- Parent: <parent 2> -->
|
|
|
|
|
<!-- Title: <title> -->
|
2020-06-25 00:36:08 -05:00
|
|
|
|
<!-- Attachment: <local path> -->
|
2021-01-04 13:08:58 +02:00
|
|
|
|
<!-- Label: <label 1> -->
|
|
|
|
|
<!-- Label: <label 2> -->
|
2016-10-25 17:23:28 +07:00
|
|
|
|
|
|
|
|
|
<page contents>
|
|
|
|
|
```
|
|
|
|
|
|
2020-07-25 10:58:32 +03:00
|
|
|
|
There can be any number of `Parent` headers, if Mark can't find specified
|
|
|
|
|
parent by title, Mark creates it.
|
2016-10-25 17:23:28 +07:00
|
|
|
|
|
2019-08-02 22:58:08 +03:00
|
|
|
|
Also, optional following headers are supported:
|
|
|
|
|
|
|
|
|
|
```markdown
|
|
|
|
|
<!-- Layout: (article|plain) -->
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
* (default) article: content will be put in narrow column for ease of
|
|
|
|
|
reading;
|
|
|
|
|
* plain: content will fill all page;
|
|
|
|
|
|
2019-08-08 15:17:44 +03:00
|
|
|
|
Mark supports Go templates, which can be included into article by using path
|
2019-08-02 22:58:08 +03:00
|
|
|
|
to the template relative to current working dir, e.g.:
|
|
|
|
|
|
|
|
|
|
```markdown
|
|
|
|
|
<!-- Include: <path> -->
|
|
|
|
|
```
|
|
|
|
|
|
2020-07-25 10:58:32 +03:00
|
|
|
|
Templates can accept configuration data in YAML format which immediately
|
|
|
|
|
follows the `Include` tag:
|
2019-08-02 22:58:08 +03:00
|
|
|
|
|
|
|
|
|
```markdown
|
|
|
|
|
<!-- Include: <path>
|
|
|
|
|
<yaml-data> -->
|
|
|
|
|
```
|
|
|
|
|
|
2020-06-25 00:36:08 -05:00
|
|
|
|
Mark also supports attachments. The standard way involves declaring an
|
|
|
|
|
`Attachment` along with the other items in the header, then have any links
|
2020-07-25 10:58:32 +03:00
|
|
|
|
with the same path:
|
2020-06-25 00:36:08 -05:00
|
|
|
|
|
|
|
|
|
```markdown
|
2020-07-25 10:58:32 +03:00
|
|
|
|
<!-- Attachment: <path-to-image> -->
|
2020-06-25 00:36:08 -05:00
|
|
|
|
|
|
|
|
|
<beginning of page content>
|
|
|
|
|
|
2020-07-25 10:58:32 +03:00
|
|
|
|
An attached link is [here](<path-to-image>)
|
2020-06-25 00:36:08 -05:00
|
|
|
|
```
|
|
|
|
|
|
2020-07-25 10:58:32 +03:00
|
|
|
|
**NOTE**: Be careful with `Attachment`! If your path string is a subset of
|
2020-06-25 00:36:08 -05:00
|
|
|
|
another longer string or referenced in text, you may get undesired behavior.
|
|
|
|
|
|
2019-08-02 22:58:08 +03:00
|
|
|
|
Mark also supports macro definitions, which are defined as regexps which will
|
|
|
|
|
be replaced with specified template:
|
|
|
|
|
|
|
|
|
|
```markdown
|
|
|
|
|
<!-- Macro: <regexp>
|
|
|
|
|
Template: <path>
|
|
|
|
|
<yaml-data> -->
|
|
|
|
|
```
|
|
|
|
|
|
2019-08-08 15:17:44 +03:00
|
|
|
|
Capture groups can be defined in the macro's <regexp> which can be later
|
|
|
|
|
referenced in the `<yaml-data>` using `${<number>}` syntax, where `<number>` is
|
|
|
|
|
number of a capture group in regexp (`${0}` is used for entire regexp match),
|
|
|
|
|
for example:
|
|
|
|
|
|
|
|
|
|
```markdown
|
|
|
|
|
<!-- Macro: MYJIRA-\d+
|
|
|
|
|
Template: ac:jira:ticket
|
|
|
|
|
Ticket: ${0} -->
|
|
|
|
|
```
|
2019-08-02 22:58:08 +03:00
|
|
|
|
|
2020-11-30 07:46:29 +00:00
|
|
|
|
### Code Blocks
|
|
|
|
|
|
|
|
|
|
If you have long code blocks, you can make them collapsible with the [Code Block Macro]:
|
|
|
|
|
|
|
|
|
|
```bash collapse
|
|
|
|
|
...
|
|
|
|
|
some long bash code block
|
|
|
|
|
...
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
And you can also add a title:
|
|
|
|
|
|
|
|
|
|
```bash collapse title Some long long bash function
|
|
|
|
|
...
|
|
|
|
|
some long bash code block
|
|
|
|
|
...
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
You can collapse or have a title without language or any mix, but the language
|
|
|
|
|
must stay in the front _if it is given_:
|
|
|
|
|
|
|
|
|
|
[<language>] ["collapse"] ["title" <your title>]
|
|
|
|
|
|
|
|
|
|
[Code Block Macro]: https://confluence.atlassian.com/doc/code-block-macro-139390.html
|
|
|
|
|
|
|
|
|
|
## Template & Macros
|
|
|
|
|
|
2019-08-02 22:58:08 +03:00
|
|
|
|
By default, mark provides several built-in templates and macros:
|
|
|
|
|
|
|
|
|
|
* template `ac:status` to include badge-like text, which accepts following
|
|
|
|
|
parameters:
|
|
|
|
|
- Title: text to display in the badge
|
|
|
|
|
- Color: color to use as background/border for badge
|
|
|
|
|
- Grey
|
|
|
|
|
- Red
|
|
|
|
|
- Yellow
|
|
|
|
|
- Green
|
|
|
|
|
- Blue
|
|
|
|
|
- Subtle: specify to fill badge with background or not
|
|
|
|
|
- true
|
|
|
|
|
- false
|
|
|
|
|
|
2019-08-06 18:07:40 +03:00
|
|
|
|
* template `ac:jira:ticket` to include JIRA ticket link. Parameters:
|
|
|
|
|
- Ticket: Jira ticket number like BUGS-123.
|
|
|
|
|
|
2019-08-02 22:58:08 +03:00
|
|
|
|
See: https://confluence.atlassian.com/conf59/status-macro-792499207.html
|
|
|
|
|
|
|
|
|
|
* macro `@{...}` to mention user by name specified in the braces.
|
|
|
|
|
|
|
|
|
|
## Template & Macros Usecases
|
|
|
|
|
|
2020-09-21 19:58:58 -07:00
|
|
|
|
### Insert Disclaimer
|
2019-08-02 22:58:08 +03:00
|
|
|
|
|
2020-09-21 19:58:58 -07:00
|
|
|
|
**disclaimer.md**
|
2019-08-02 22:58:08 +03:00
|
|
|
|
|
|
|
|
|
```markdown
|
|
|
|
|
**NOTE**: this document is generated, do not edit manually.
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**article.md**
|
|
|
|
|
```markdown
|
|
|
|
|
<!-- Space: TEST -->
|
|
|
|
|
<!-- Title: My Article -->
|
|
|
|
|
|
2020-09-21 19:58:58 -07:00
|
|
|
|
<!-- Include: disclaimer.md -->
|
2019-08-02 22:58:08 +03:00
|
|
|
|
|
|
|
|
|
This is my article.
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Insert Status Badge
|
|
|
|
|
|
|
|
|
|
**article.md**
|
|
|
|
|
|
|
|
|
|
```markdown
|
|
|
|
|
<!-- Space: TEST -->
|
|
|
|
|
<!-- Title: TODO List -->
|
|
|
|
|
|
|
|
|
|
<!-- Macro: :done:
|
|
|
|
|
Template: ac:status
|
|
|
|
|
Title: DONE
|
|
|
|
|
Color: Green -->
|
|
|
|
|
|
|
|
|
|
<!-- Macro: :todo:
|
|
|
|
|
Template: ac:status
|
|
|
|
|
Title: TODO
|
|
|
|
|
Color: Blue -->
|
|
|
|
|
|
|
|
|
|
* :done: Write Article
|
|
|
|
|
* :todo: Publish Article
|
|
|
|
|
```
|
|
|
|
|
|
2020-10-19 16:46:52 +02:00
|
|
|
|
### Insert Table of Contents
|
|
|
|
|
|
|
|
|
|
```markdown
|
|
|
|
|
<!-- Include: ac:toc -->
|
|
|
|
|
```
|
|
|
|
|
|
2020-11-30 07:45:02 +00:00
|
|
|
|
If default TOC looks don't find a way to your heart, try [parametrizing it][Confluence TOC Macro], for example:
|
|
|
|
|
|
|
|
|
|
```markdown
|
|
|
|
|
<!-- Macro: :toc:
|
|
|
|
|
Template: ac:toc
|
|
|
|
|
Printable: 'false'
|
|
|
|
|
MinLevel: 2 -->
|
|
|
|
|
|
|
|
|
|
# This is my nice title
|
|
|
|
|
|
|
|
|
|
:toc:
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
You can call the `Macro` as you like but the `Template` field must have the `ac:toc` value.
|
|
|
|
|
Also, note the single quotes around `'false'`.
|
|
|
|
|
|
|
|
|
|
See [Confluence TOC Macro] for the list of parameters - keep in mind that here
|
|
|
|
|
they start with capital letters. Every skipped field will have the default
|
|
|
|
|
value, so feel free to include only the ones that you require.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[Confluence TOC Macro]:https://confluence.atlassian.com/conf59/table-of-contents-macro-792499210.html
|
|
|
|
|
|
2020-10-19 16:46:52 +02:00
|
|
|
|
### Insert Jira Ticket
|
2019-08-02 22:58:08 +03:00
|
|
|
|
|
|
|
|
|
**article.md**
|
|
|
|
|
|
|
|
|
|
```markdown
|
|
|
|
|
<!-- Space: TEST -->
|
|
|
|
|
<!-- Title: TODO List -->
|
|
|
|
|
|
|
|
|
|
<!-- Macro: MYJIRA-\d+
|
2019-08-06 18:07:40 +03:00
|
|
|
|
Template: ac:jira:ticket
|
2019-08-02 22:58:08 +03:00
|
|
|
|
Ticket: ${0} -->
|
|
|
|
|
|
|
|
|
|
See task MYJIRA-123.
|
|
|
|
|
```
|
|
|
|
|
|
2020-07-25 12:10:26 +03:00
|
|
|
|
## Installation
|
|
|
|
|
|
|
|
|
|
### Go Get
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
go get -v github.com/kovetskiy/mark
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Releases
|
|
|
|
|
|
|
|
|
|
[Download a release from the Releases page](https://github.com/kovetskiy/mark/releases)
|
|
|
|
|
|
|
|
|
|
### Docker
|
|
|
|
|
|
|
|
|
|
```bash
|
2020-07-29 09:51:49 +02:00
|
|
|
|
$ docker run --rm -i kovetskiy/mark:latest mark <params>
|
2020-07-25 12:10:26 +03:00
|
|
|
|
```
|
|
|
|
|
|
2019-08-02 22:58:08 +03:00
|
|
|
|
## Usage
|
|
|
|
|
|
2015-09-20 00:34:52 +06:00
|
|
|
|
```
|
2016-10-25 17:23:28 +07:00
|
|
|
|
mark [options] [-u <username>] [-p <password>] [-k] [-l <url>] -f <file>
|
2020-11-20 08:44:41 -06:00
|
|
|
|
mark [options] [-u <username>] [-p <password>] [-k] [-b <url>] -f <file>
|
|
|
|
|
mark [options] [-u <username>] [-p <password>] [--drop-h1] -f <file>
|
2015-09-20 00:34:52 +06:00
|
|
|
|
mark -v | --version
|
|
|
|
|
mark -h | --help
|
|
|
|
|
```
|
|
|
|
|
|
2016-11-30 18:47:05 +07:00
|
|
|
|
- `-u <username>` — Use specified username for updating Confluence page.
|
|
|
|
|
- `-p <password>` — Use specified password for updating Confluence page.
|
|
|
|
|
- `-l <url>` — Edit specified Confluence page.
|
|
|
|
|
If -l is not specified, file should contain metadata (see above).
|
2020-11-20 08:44:41 -06:00
|
|
|
|
- `-b <url>` or `--base-url <url>` – Base URL for Confluence.
|
|
|
|
|
Alternative option for base_url config field.
|
2016-11-30 18:47:05 +07:00
|
|
|
|
- `-f <file>` — Use specified markdown file for converting to html.
|
|
|
|
|
- `-c <file>` — Specify configuration file which should be used for reading
|
|
|
|
|
Confluence page URL and markdown file path.
|
|
|
|
|
- `-k` — Lock page editing to current user only to prevent accidental
|
|
|
|
|
manual edits over Confluence Web UI.
|
2020-11-20 08:44:41 -06:00
|
|
|
|
- `--drop-h1` – Don't include H1 headings in Confluence output.
|
2016-11-30 18:47:05 +07:00
|
|
|
|
- `--dry-run` — Show resulting HTML and don't update Confluence page content.
|
2021-01-04 15:42:34 +02:00
|
|
|
|
- `--minor-edit` — Don't send notifications while updating Confluence page.
|
2016-11-30 18:47:05 +07:00
|
|
|
|
- `--trace` — Enable trace logs.
|
2020-11-20 08:44:41 -06:00
|
|
|
|
- `-v | --version` — Show version.
|
2016-11-30 18:47:05 +07:00
|
|
|
|
- `-h | --help` — Show help screen and call 911.
|
2019-11-25 19:53:10 +03:00
|
|
|
|
|
2020-07-25 10:58:32 +03:00
|
|
|
|
You can store user credentials in the configuration file, which should be
|
|
|
|
|
located in ~/.config/mark with the following format (TOML):
|
|
|
|
|
|
|
|
|
|
```toml
|
|
|
|
|
username = "smith"
|
|
|
|
|
password = "matrixishere"
|
|
|
|
|
# If you are using Confluence Cloud add the /wiki suffix to base_url
|
|
|
|
|
base_url = "http://confluence.local"
|
|
|
|
|
```
|
|
|
|
|
|
2021-01-04 15:42:34 +02:00
|
|
|
|
**NOTE**: Labels aren't supported when using `minor-edit`!
|
|
|
|
|
|
2019-11-25 19:53:10 +03:00
|
|
|
|
# Tricks
|
|
|
|
|
|
2020-07-28 11:05:17 +03:00
|
|
|
|
## Continuous Integration
|
2019-11-25 19:53:10 +03:00
|
|
|
|
|
2020-07-28 11:05:17 +03:00
|
|
|
|
It's quite trivial to integrate Mark into a CI/CD system, here is an example with [Snake CI](https://snake-ci.com/)
|
|
|
|
|
in case of self-hosted Bitbucket Server / Data Center.
|
2019-11-25 19:53:10 +03:00
|
|
|
|
|
|
|
|
|
```yaml
|
|
|
|
|
stages:
|
2020-07-28 11:05:17 +03:00
|
|
|
|
- sync
|
|
|
|
|
|
|
|
|
|
Sync documentation:
|
|
|
|
|
stage: sync
|
|
|
|
|
only:
|
|
|
|
|
branches:
|
|
|
|
|
- main
|
|
|
|
|
image: kovetskiy/mark
|
|
|
|
|
commands:
|
|
|
|
|
- for file in $(find -type f -name '*.md'); do
|
|
|
|
|
echo "> Sync $file";
|
|
|
|
|
mark -u $MARK_USER -p $MARK_PASS -b $MARK_URL -f $file || exit 1;
|
|
|
|
|
echo;
|
|
|
|
|
done
|
2019-11-25 19:53:10 +03:00
|
|
|
|
```
|
|
|
|
|
|
2020-07-28 11:05:17 +03:00
|
|
|
|
In this example, I'm using the `kovetskiy/mark` image for creating a job container where the
|
|
|
|
|
repository with documentation will be cloned to. The following command finds all `*.md` files and runs mark against them one by one:
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
for file in $(find -type f -name '*.md'); do
|
|
|
|
|
echo "> Sync $file";
|
|
|
|
|
mark -u $MARK_USER -p $MARK_PASS -b $MARK_URL -f $file || exit 1;
|
|
|
|
|
echo;
|
|
|
|
|
done
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
The following directive tells the CI to run this particular job only if the changes are pushed into the
|
|
|
|
|
`main` branch. It means you can safely push your changes into feature branches without being afraid
|
|
|
|
|
that they automatically shown in Confluence, then go through the reviewal process and automatically
|
|
|
|
|
deploy them when PR got merged.
|
|
|
|
|
|
|
|
|
|
```yaml
|
|
|
|
|
only:
|
|
|
|
|
branches:
|
|
|
|
|
- main
|
|
|
|
|
```
|