hunyadi / md2conf Goto Github PK
View Code? Open in Web Editor NEWPublish Markdown files to Confluence wiki
License: MIT License
Publish Markdown files to Confluence wiki
License: MIT License
Unfortunately, sub-items/nested lists (https://commonmark.org/help/tutorial/10-nestedLists.html) are not working properly:
$ head -n11 testing.md
<!-- confluence-page-id: 367198209 -->
<!-- confluence-space-key: ~62dfb0d2b6b0b70770d7d76c -->
* Foo
* Bar
* foo
* foo1
* bar1
* bar
* foo2
* bar2
This results in a one-level list in Confluence. I am wondering if would be possible to implement this feature?
Hi,
I found that commit
This related to self ref href.
With markdown the valid syntax is :
## Test of link
## Test of Href
[test](#test-of-link)
With [test](#Test-of-link)
markdown lint will show a warning
However the confluence link is not generated properly as it should be smth like:
https://url-of-page#1.2.4.-Test-of-link
1.2.4 is the index in the toc and first letter of the lin shall be capitalize.
Something related to this portion of the code might need an update to make that work:
if (
not relative_url.scheme
and not relative_url.netloc
and not relative_url.path
and not relative_url.params
and not relative_url.query
):
LOGGER.debug(f"found local URL: {url}")
anchor.attrib["href"] = url
return
Thanks in advance
See https://docs.gitlab.com/ee/user/markdown.html#url-auto-linking
This behavior corresponds to default Confluence behavior when you insert a simple URL.
Would it be nice to have this feature? Maybe this behavior can be enabled/disabled via cmdline option?
At the moment you need the following to have link in Confluence which is clickable:
See [https://foobar.com](https://foobar.com) for more information.
Instead of:
See https://foobar.com for more information.
On the other side there might be cases where you explicitly do not want a URL to be clickable π€
The file I'm trying to publish has an image linked in it.
The Confluence API returns a 400 when I use md2conf.
Unfortunately the API is not very talkative about the reason of the error, and perhaps the image is a red herring and the real reson is elsewhere.
Here is the stacktrace:
2023-05-30 17:46:45,724 - INFO - upload_attachment [221] - Uploading attachment: ./multi-sign-graph.png
Traceback (most recent call last):
File "/opt/hostedtoolcache/Python/3.10.11/x64/lib/python3.10/runpy.py", line 196, in _run_module_as_main
return _run_code(code, main_globals, None,
File "/opt/hostedtoolcache/Python/3.10.11/x64/lib/python3.10/runpy.py", line 86, in _run_code
exec(code, run_globals)
File "/opt/hostedtoolcache/Python/3.10.11/x64/lib/python3.10/site-packages/md2conf/__main__.py", line 59, in <module>
synchronize_page(api, args.mdfile)
File "/opt/hostedtoolcache/Python/3.10.11/x64/lib/python3.10/site-packages/md2conf/application.py", line 28, in synchronize_page
update_document(api, document, base_path)
File "/opt/hostedtoolcache/Python/3.10.11/x64/lib/python3.10/site-packages/md2conf/application.py", line 11, in update_document
api.upload_attachment(
File "/opt/hostedtoolcache/Python/3.10.11/x64/lib/python3.10/site-packages/md2conf/api.py", line 228, in upload_attachment
response.raise_for_status()
File "/opt/hostedtoolcache/Python/3.10.11/x64/lib/python3.10/site-packages/requests/models.py", line 10[21](https://github.com/[β¦]), in raise_for_status
raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 400 Client Error: Bad Request for url: https://[β¦]/child/attachment
Hi there, thanks for writing this project - its proving super helpful for one of my use cases.
I've noticed something that seems to be throwing consistent exceptions. (haven't had time to dig in yet but thought I'd log this one in case)
in a markdown file in a location like ./foo/bar.md
that has a relative link to [link](../blah/something.md)
It appears that the code throws this exception - Even though the relative link is valid for that file location.
File "/Users/user/src/work/md2conf/md2conf/converter.py", line 260, in _transform_link
raise DocumentError(f"relative URL points to outside base path: {url}")
md2conf.converter.DocumentError: relative URL points to outside base path: ../blah/something.md
Will attempt to debug this soon and may submit a PR if I figure it out.
Thanks!
I'm trying to create presentations using https://marp.app/ and then publish them into confluence using md2conf. Everything works well except Marp uses frontmatter to contain meta information. (See also)
Is it possible to drop the frontmatter?
Since version 0.19 I experience a problem when rendering email addresses. The following error message appears:
2023-10-19 06:33:28,517 - INFO - _synchronize_page [87] - Synchronizing page: README.md Traceback (most recent call last): File "<frozen runpy>", line 198, in _run_module_as_main File "<frozen runpy>", line 88, in _run_code File "/usr/local/lib/python3.12/site-packages/md2conf/__main__.py", line 85, in <module> Application(api, ConfluenceDocumentOptions(args.generated_by)).synchronize( File "/usr/local/lib/python3.12/site-packages/md2conf/application.py", line 34, in synchronize self.synchronize_page(path) File "/usr/local/lib/python3.12/site-packages/md2conf/application.py", line 41, in synchronize_page self._synchronize_page(page_path, dict()) File "/usr/local/lib/python3.12/site-packages/md2conf/application.py", line 88, in _synchronize_page document = ConfluenceDocument(page_path, self.options, page_metadata) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.12/site-packages/md2conf/converter.py", line 5[31](https://gitlab.*****), in __init__ converter.visit(self.root) File "/usr/local/lib/python3.12/site-packages/md2conf/converter.py", line 198, in visit self.visit(source) File "/usr/local/lib/python3.12/site-packages/md2conf/converter.py", line 198, in visit self.visit(source) File "/usr/local/lib/python3.12/site-packages/md2conf/converter.py", line 194, in visit target = self.transform(source) ^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.12/site-packages/md2conf/converter.py", line [42](https://gitlab*****)0, in transform return self._transform_link(child) ^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.12/site-packages/md2conf/converter.py", line 260, in _transform_link raise DocumentError(f"unable to find matching page for URL: {url}") md2conf.converter.DocumentError: unable to find matching page for URL: mailto:[email protected]
With the markdown file
<!-- confluence-space-key: MYSPACE -->
<!-- confluence-page-id: 1234567890 -->
# example
![confluence log](./img/confluence.png)
I get
2023-09-18 15:20:46,528 - ERROR - <module> [93] - {'statusCode': 400, 'data': {'authorized': True, 'valid': True, 'errors': [], 'successful': True}, 'message': 'com.atlassian.confluence.api.service.exceptions.BadRequestException: Cannot add a new attachment with same file name as an existing attachment: confluence.png'}
According to the docs you can change the space key on per-document basis:
<!-- confluence-space-key: DAP -->
This overrides the default space set via command-line arguments or environment variables.
This doesn't seem to work for me (someother
is another valid space key) :
$ head testing.md -n2
<!-- confluence-page-id: 367198209 -->
<!-- confluence-space-key: ~62dfb0d2b6b0b70770d7d76c -->
$ python3 -m md2conf testing.md -s someother
2023-08-23 12:39:34,798 - INFO - _synchronize_page [87] - Synchronizing page: testing.md
2023-08-23 12:39:34,978 - INFO - update_page [363] - Updating page: 367198209
2023-08-23 12:39:35,086 - ERROR - <module> [89] - 400 Client Error: Bad Request for url: https://atix.atlassian.net/wiki/rest/api/content/367198209
2023-08-23 12:39:35,086 - ERROR - <module> [94] - {'statusCode': 400, 'data': {'authorized': True, 'valid': False, 'errors': [{'message': {'key': "You can't change an existing page's space.", 'args': []}}], 'successful': False}, 'message': 'com.atlassian.confluence.api.service.exceptions.BadRequestException: Could not update Content of type : class com.atlassian.confluence.pages.Page with id 367198209'}
Another question is why is there a space key required via command-line arguments or environment variables at all? A space key tag in the document should be sufficient or not?
$ echo $CONFLUENCE_SPACE_KEY
$ head testing.md -n2
<!-- confluence-space-key: ~62dfb0d2b6b0b70770d7d76c -->
<!-- confluence-page-id: 367198209 -->
$ python3 -m md2conf testing.md
Traceback (most recent call last):
File "/usr/lib64/python3.10/runpy.py", line 196, in _run_module_as_main
return _run_code(code, main_globals, None,
File "/usr/lib64/python3.10/runpy.py", line 86, in _run_code
exec(code, run_globals)
File "/home/jloeser/devel/envs/md2conf-env/lib/python3.10/site-packages/md2conf/__main__.py", line 82, in <module>
with ConfluenceAPI(
File "/home/jloeser/devel/envs/md2conf-env/lib/python3.10/site-packages/md2conf/api.py", line 117, in __init__
raise ConfluenceError("Confluence space key not specified")
md2conf.api.ConfluenceError: Confluence space key not specified
Tested version of md2conf is revision 6627f42.
Hello, first of all thanks for this great work.
Is there any way to export a subfolder as a file?
When I export a subfolder that contains some .md files they are being exported to the root page id (the one defined by the argument: -r $page_id) so thereΒ΄s no way to have child pages like the ones used in Confluence.
Any workaround for this?
Thank you!
Hello,
Just looking for assistance on what would be the best way to make md2conf
compatible with terraform-docs
.
I could successfully publish README.md existing in current repo but fail to upload every generated by terraform-docs
sequence of commands:
terraform-docs markdown document . --output-file README.md --sort-by required
python -m md2conf -l debug README.md
Exception
`
2024-04-01 19:24:11,572 - INFO - _synchronize_page [76] - Synchronizing page: adl-athena-workgroups/README.md
2024-04-01 19:24:11,580 - DEBUG - registerExtensions [182] - Successfully loaded extension "markdown.extensions.admonition.AdmonitionExtension".
2024-04-01 19:24:11,580 - DEBUG - build_extension [226] - Successfully imported extension module "markdown.extensions.tables".
2024-04-01 19:24:11,580 - DEBUG - registerExtensions [182] - Successfully loaded extension "markdown.extensions.tables.TableExtension".
2024-04-01 19:24:11,582 - DEBUG - build_extension [226] - Successfully imported extension module "markdown.extensions.fenced_code".
2024-04-01 19:24:11,583 - DEBUG - registerExtensions [182] - Successfully loaded extension "markdown.extensions.fenced_code.FencedCodeExtension".
2024-04-01 19:24:11,587 - DEBUG - build_extension [226] - Successfully imported extension module "pymdownx.magiclink".
2024-04-01 19:24:11,589 - DEBUG - registerExtensions [182] - Successfully loaded extension "pymdownx.magiclink.MagiclinkExtension".
2024-04-01 19:24:11,590 - DEBUG - build_extension [226] - Successfully imported extension module "pymdownx.tilde".
2024-04-01 19:24:11,590 - DEBUG - registerExtensions [182] - Successfully loaded extension "pymdownx.tilde.DeleteSubExtension".
2024-04-01 19:24:11,590 - DEBUG - registerExtensions [182] - Successfully loaded extension "markdown.extensions.sane_lists.SaneListExtension".
Traceback (most recent call last):
File "/opt/homebrew/Caskroom/miniconda/base/envs/310/lib/python3.10/site-packages/md2conf/converter.py", line 86, in _elements_from_strings
return ET.fromstringlist(data, parser=parser)
File "src/lxml/etree.pyx", line 3309, in lxml.etree.fromstringlist
File "src/lxml/parser.pxi", line 1331, in lxml.etree._FeedParser.feed
File "src/lxml/parser.pxi", line 1451, in lxml.etree._FeedParser.feed
File "src/lxml/parser.pxi", line 624, in lxml.etree._ParserContext._handleParseResult
File "src/lxml/parser.pxi", line 633, in lxml.etree._ParserContext._handleParseResultDoc
File "src/lxml/parser.pxi", line 743, in lxml.etree._handleParseResult
File "src/lxml/parser.pxi", line 672, in lxml.etree._raiseParseError
File "", line 201
lxml.etree.XMLSyntaxError: Opening and ending tag mismatch: br line 201 and pre, line 201, column 70
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/opt/homebrew/Caskroom/miniconda/base/envs/310/lib/python3.10/runpy.py", line 196, in _run_module_as_main
return _run_code(code, main_globals, None,
File "/opt/homebrew/Caskroom/miniconda/base/envs/310/lib/python3.10/runpy.py", line 86, in _run_code
exec(code, run_globals)
File "/opt/homebrew/Caskroom/miniconda/base/envs/310/lib/python3.10/site-packages/md2conf/main.py", line 118, in
).synchronize(args.mdpath)
File "/opt/homebrew/Caskroom/miniconda/base/envs/310/lib/python3.10/site-packages/md2conf/application.py", line 34, in synchronize
self.synchronize_page(path)
File "/opt/homebrew/Caskroom/miniconda/base/envs/310/lib/python3.10/site-packages/md2conf/application.py", line 41, in synchronize_page
self._synchronize_page(page_path, {})
File "/opt/homebrew/Caskroom/miniconda/base/envs/310/lib/python3.10/site-packages/md2conf/application.py", line 77, in _synchronize_page
document = ConfluenceDocument(page_path, self.options, page_metadata)
File "/opt/homebrew/Caskroom/miniconda/base/envs/310/lib/python3.10/site-packages/md2conf/converter.py", line 568, in init
self.root = elements_from_strings(content)
File "/opt/homebrew/Caskroom/miniconda/base/envs/310/lib/python3.10/site-packages/md2conf/converter.py", line 97, in elements_from_strings
return _elements_from_strings(dtd_path, items)
File "/opt/homebrew/Caskroom/miniconda/base/envs/310/lib/python3.10/site-packages/md2conf/converter.py", line 88, in _elements_from_strings
raise ParseError(e)
md2conf.converter.ParseError: Opening and ending tag mismatch: br line 201 and pre, line 201, column 70 (, line 201)
`
Can not share file content but maybe by the stack trace it will be clear what is wrong.
I don't know if it's not possible yet or I'm missing something, thanks for the great work!
When I publish my markdown file to confluence, the confluence page shows a prompt at the top of the page saying "This page has been generated with a tool.". How do I disable it?
Currently, only external links are supported. However, there might be documents using header anchors for internal reference.
Example:
$ cat internal-link.md
<!-- confluence-page-id: 367198209 -->
Foo
# Test1
Bar
# Test2
See [link](#test1)
See [link](internal-link.md#test2)
Both links are valid (GitLab flavored) Markdown according to https://docs.gitlab.com/ee/user/markdown.html#links
Actual behavior is DocumentError
:
2023-08-16 12:15:33,798 - DEBUG - _transform_link [180] - found link #test1 relative to /home/user/internal-link.md
Traceback (most recent call last):
...
md2conf.converter.DocumentError: relative URL points to outside base path: #test1
Would be nice to either convert them them accordingly in Confluence (no idea if this is feasible) or to somehow ignore them/change representation. In any case, a valid document should be created.
We already use an Info Panel for the generated-by message at the very top of the document.
Could we enable this feature also in the normal text including its derivatives ("Note", "Success", "Warning", "Error")?
The current notation I am using in Markdown for such boxes (there is no concept of "Info Panels" in Markdown) is:
Normal text.
> **_NOTE:_**
> This is my Note. There can be **many** lines.
> Last one is this one.
Normal text.
Github has support for the following style of alerts. https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#alerts
When used today they end up looking like this in Confluence.
But should end up looking like this
Github alerts mapped to Confluence panels
Github | Confluence |
---|---|
NOTE | Note |
TIP | Info or maybe Success (Tip is green on Github side so maybe Success?) |
IMPORTANT | Info or maybe Success |
WARNING | Warning |
CAUTION | Error |
Figure out a way to convert to Admonitions might make sense so its consistent. But also could be its own code path.
Hey,
I would like to use your script in an ansible playbook. As the publish part is already done, and I really like that to stay in native ansible, I would only need to convert my markdown with your python script.
Is this possible somehow?
Hi,
in the Atlasian python API, there is a cloud boolean parameter, which change the API used.
I do not think it possible to do with md2conf as of today, moreover you do not use the python atlasian toolkit.
Is there a parameter to change the api used ?
thanks in advance
Hi! When trying to use md2conf in a GitHub action I am getting this error:
Traceback (most recent call last):
File "/usr/lib/python3.8/runpy.py", line 194, in _run_module_as_main
return _run_code(code, main_globals, None,
File "/usr/lib/python3.8/runpy.py", line 87, in _run_code
exec(code, run_globals)
File "/home/runner/.local/lib/python3.8/site-packages/md2conf/__main__.py", line 59, in <module>
synchronize_page(api, args.mdfile)
File "/home/runner/.local/lib/python3.8/site-packages/md2conf/application.py", line 28, in synchronize_page
update_document(api, document, base_path)
File "/home/runner/.local/lib/python3.8/site-packages/md2conf/application.py", line [11](https://github.com/scrive/β¦#step:5:12), in update_document
api.upload_attachment(
File "/home/runner/.local/lib/python3.8/site-packages/md2conf/api.py", line 240, in upload_attachment
self._update_attachment(page_id, attachment_id, version, attachment_name)
File "/home/runner/.local/lib/python3.8/site-packages/md2conf/api.py", line 245, in _update_attachment
id = attachment_id.removeprefix("att")
AttributeError: 'str' object has no attribute 'removeprefix'
Is it something I can fix on my end?
Confluence version: 8.2.3 Server Edition
markdown-to-confluence installed with pip, version: 0.1.10
Confluence returns: "<Response [200]>"
Exception message:
2023-12-06 13:47:11,617 - INFO - _synchronize_page [87] - Synchronizing page: test.md
Traceback (most recent call last):
File "/opt/homebrew/lib/python3.11/site-packages/requests/models.py", line 971, in json
return complexjson.loads(self.text, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/homebrew/Cellar/[email protected]/3.11.6_1/Frameworks/Python.framework/Versions/3.11/lib/python3.11/json/__init__.py", line 346, in loads
return _default_decoder.decode(s)
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/homebrew/Cellar/[email protected]/3.11.6_1/Frameworks/Python.framework/Versions/3.11/lib/python3.11/json/decoder.py", line 337, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/homebrew/Cellar/[email protected]/3.11.6_1/Frameworks/Python.framework/Versions/3.11/lib/python3.11/json/decoder.py", line 355, in raw_decode
raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<frozen runpy>", line 198, in _run_module_as_main
File "<frozen runpy>", line 88, in _run_code
File "/opt/homebrew/lib/python3.11/site-packages/md2conf/__main__.py", line 85, in <module>
Application(api, ConfluenceDocumentOptions(args.generated_by)).synchronize(
File "/opt/homebrew/lib/python3.11/site-packages/md2conf/application.py", line 34, in synchronize
self.synchronize_page(path)
File "/opt/homebrew/lib/python3.11/site-packages/md2conf/application.py", line 41, in synchronize_page
self._synchronize_page(page_path, dict())
File "/opt/homebrew/lib/python3.11/site-packages/md2conf/application.py", line 94, in _synchronize_page
self._update_document(document, base_path)
File "/opt/homebrew/lib/python3.11/site-packages/md2conf/application.py", line 104, in _update_document
self.api.update_page(document.id.page_id, content)
File "/opt/homebrew/lib/python3.11/site-packages/md2conf/api.py", line 343, in update_page
page = self.get_page(page_id)
^^^^^^^^^^^^^^^^^^^^^^
File "/opt/homebrew/lib/python3.11/site-packages/md2conf/api.py", line 320, in get_page
data = typing.cast(Dict[str, JsonType], self._invoke(path, query))
^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/homebrew/lib/python3.11/site-packages/md2conf/api.py", line 188, in _invoke
return response.json()
^^^^^^^^^^^^^^^
File "/opt/homebrew/lib/python3.11/site-packages/requests/models.py", line 975, in json
raise RequestsJSONDecodeError(e.msg, e.doc, e.pos)
requests.exceptions.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
We are using markdown in Github to support collapsible sections. See here. Would like that to be converted into a Confluence Expand Macro
Noticed today that the markdown
python library doesn't seemingly parse things correctly when inside the details/summary
blocks. For example if you nest a markdown list inside details
it doesn't run it into a <ul><li>
. Unsure if this issue is 2 things or not.
details/summary
blocks better so that html is returned correctlydetails/summary
blocks into Confluence Expand Macros
Likely they are not dependent but would likely want both for to have correctly rendered data.
Hi,
I have some Gitlab Markdown documents that I want to export to Confluence. Everything is working smooth except relative links to files in gitlab.
Example:
- [.gitlab-ci.yml](.gitlab-ci.yml)
It returns the following error:
Processing README.md 2023-11-06 11:35:02,249 - INFO - _synchronize_page [87] - Synchronizing page: README.md Traceback (most recent call last): File "<frozen runpy>", line 198, in _run_module_as_main File "<frozen runpy>", line 88, in _run_code File "/usr/local/lib/python3.12/site-packages/md2conf/__main__.py", line 85, in <module> Application(api, ConfluenceDocumentOptions(args.generated_by)).synchronize( File "/usr/local/lib/python3.12/site-packages/md2conf/application.py", line 34, in synchronize self.synchronize_page(path) File "/usr/local/lib/python3.12/site-packages/md2conf/application.py", line 41, in synchronize_page self._synchronize_page(page_path, dict()) File "/usr/local/lib/python3.12/site-packages/md2conf/application.py", line 88, in _synchronize_page document = ConfluenceDocument(page_path, self.options, page_metadata) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.12/site-packages/md2conf/converter.py", line 531, in __init__ converter.visit(self.root) File "/usr/local/lib/python3.12/site-packages/md2conf/converter.py", line 198, in visit self.visit(source) File "/usr/local/lib/python3.12/site-packages/md2conf/converter.py", line 194, in visit target = self.transform(source) ^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.12/site-packages/md2conf/converter.py", line 420, in transform return self._transform_link(child) ^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.12/site-packages/md2conf/converter.py", line 260, in _transform_link raise DocumentError(f"unable to find matching page for URL: {url}") md2conf.converter.DocumentError: unable to find matching page for URL: .gitlab-ci.yml
Is there an option or possibility to add a feature, that relative links will be converted to text, so the pipeline will not fail? Or does someone have a better idea?
Thanks a lot!
I generate a Table of Contents that works in Github rendered Readmes but when uploaded to Confluence it does not work since there are a handful of cases that make them not find the right heading.
Biggest one is that links are case sensitive. Most generators doctoc or chatgpt or whatever just make everything lowercase b/c that is easiest to make things consistent. Confluence on the other hand is case sensitive with links. https://support.atlassian.com/confluence-cloud/docs/insert-links-and-anchors/#Create-and-insert-links
:
, (
, and )
characters need to be url encoded:-
ends up being turned into :
*
characters are ignored completely and removed.Some examples
github TOC entry | what confluence needs to work |
---|---|
- [How to use `CUSTOM_DEF` parameters](#how-to-use-custom_def-parameters) |
#How-to-use-CUSTOM_DEF-parameters |
- [Define custom naming (for Thing)](#define-custom-naming-for-thing) |
#Define-custom-naming-%28for-Thing-2%29 |
- [**Next section:** Inputs and outputs](#next-section-inputs-and-outputs) |
Next-section:Inputs-and-outputs |
I run this bash script to find all the TOCs that are generated (in my case if it has the doctoc
start/end comments) and replace all of them accordingly to match and work on confluence before uploading them. Probably could make it smarter and use those or if we find a list with a link in it then we can assume its a TOC and process it.
#!/bin/bash
# Script to modify the TOC links in markdown files to be compatible with Confluence.
# Details on links in confluence can be found here https://support.atlassian.com/confluence-cloud/docs/insert-links-and-anchors/#Create-and-insert-links
# Couple things to note that are different than github TOC
# * Links are case sensitive
# * :, (, and ) characters need to be url encoded
# * :- is treated as :
# * ` and * characters are ignored
# Function to URL encode specific characters
url_encode() {
echo "$1" | sed -e 's/:/%3A/g' -e 's/(/%28/g' -e 's/)/%29/g'
}
# Get the directory name from the command line argument
directory_name="$WORKING_DIR"
# Check if the directory name is provided
if [ -z "$directory_name" ]; then
echo "Please provide a directory name."
exit 1
fi
# Update the base directory with the provided directory name
base_dir="$directory_name"
echo "Processing $base_dir"
# Find all markdown files in the specified directory
md_files=$(find "$base_dir" -type f -name "*.md")
# Define the TOC markers
toc_start_marker="<!-- START doctoc generated TOC please keep comment here to allow auto update -->"
toc_end_marker="<!-- END doctoc generated TOC please keep comment here to allow auto update -->"
# Process each markdown file
for md_file in $md_files; do
echo "Processing $md_file..."
# Read the contents of the file
lines=$(cat "$md_file")
# Flag to track when we are inside the TOC
inside_toc=false
# Temporary file to store updated lines
temp_file=$(mktemp)
# Process lines and update the TOC
while IFS= read -r line; do
if [[ "$line" == *"$toc_start_marker"* ]]; then
inside_toc=true
echo "TOC found in $md_file"
fi
if $inside_toc && [[ "$line" =~ ^[[:space:]]*-[[:space:]]*\[.*\]\(#.*\) ]]; then
# Extract the link text without brackets using awk
link_text=$(echo "$line" | awk -F'[][]' '{print $2}')
# Replace spaces with hyphens
new_id=$(echo "$link_text" | sed 's/ /-/g')
# Remove ` and * characters
new_id=$(echo "$new_id" | sed 's/[\`*]//g')
# Replace :- with :
new_id=$(echo "$new_id" | sed 's/:-/:/g')
# URL encode : ( ) characters
new_id=$(url_encode "$new_id")
# Construct the updated line with new_id
updated_line=$(echo "$line" | sed -E "s/\(#.*\)/(#$new_id)/")
echo "Original toc line: $line"
echo "Updated toc line: $updated_line"
echo "$updated_line" >> "$temp_file"
continue
fi
echo "$line" >> "$temp_file"
if [[ "$line" == *"$toc_end_marker"* ]]; then
inside_toc=false
echo "end of TOC found for $md_file"
fi
done <<< "$lines"
# Write the updated lines back to the file
mv "$temp_file" "$md_file"
echo "TOC links updated successfully in $md_file."
done
echo "All markdown files processed."
Would like to not have to do this hack and instead md2conf be smart enough to process it for me and do some processing on the inputs to update any TOC type links to work with Confluence.
PS: Thanks for creating this tool btw it works great π π π
I had some markdowns that ended up not generating valid xhtml that wouldn't upload to Confluence. I did not know till deploy time.
So need a way to validate it and would like to not be reliant on api keys and actually uploading to validate the files are good before then.
Tried to run the following and got this error
md2conf documentation --generated-by "Zender" -r 733642769 --local
md2conf.properties.ConfluenceError: Confluence domain not specified
So after specifying all the ENV vars with fake values, it would run but output this error.
CONFLUENCE_USER_NAME="yyy" CONFLUENCE_SPACE_KEY="xxx" CONFLUENCE_DOMAIN="zzz" md2conf documentation --generated-by "Zender" -r 733642769 --local
File "/Users/zender/.local/pipx/venvs/markdown-to-confluence/lib/python3.12/site-packages/md2conf/processor.py", line 83, in _get_page
raise ValueError("required: page ID for local output")
ValueError: required: page ID for local output
Ideally it should not matter that there is not a page id specified.
I think if we just set the page_id
at this code to something random it would work if the local flag was set.
Lines 81 to 83 in 94a0eee
When a markdown document references a picture in a subfolder:
![my picture](images/picture.jpg)
The picture is properly uploaded as attachment to the confluence page. But it is not displayed.
When looking at the attachment in confluence (which is named images/picture.jpg
, I cannot display the picture either.
This is a common use case, so documenting this as limitation is not very friendly.
I just published a test page
!!! info "optional explicit title within double quotes"
Any number of other indented markdown elements.
This is the second paragraph.
!!! warning
You should note that the title will be automatically capitalized.
!!! tip
You should note that the title will be automatically capitalized.
!!! note
"Don't try this at home"
...
Appears to render in confluence as
A declarative, efficient, and flexible JavaScript library for building user interfaces.
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. πππ
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google β€οΈ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.