diff --git a/CHANGELOG.md b/CHANGELOG.md index 6cf20db..9b84fce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,12 @@ # Changelog +## [Version 1.1.2](https://github.com/dataiku/dss-plugin-confluence/releases/tag/v1.1.2) - Feature release - 2025-12-05 + +- Add support for links to flow_zone, scenario, dashboard, recipe, managed_folder, statistics_worksheet, lambda_service and analysis + ## [Version 1.1.1](https://github.com/dataiku/dss-plugin-confluence/releases/tag/v1.1.1) - Feature release - 2025-06-28 - Fix following API change -- Add support for links to flow_zone, scenario, dashboard, recipe, managed_folder, statistics_worksheet, lambda_service ## [Version 1.1.0](https://github.com/dataiku/dss-plugin-confluence/releases/tag/v1.1.0) - Feature release - 2024-06-14 diff --git a/parameter-sets/confluence-login/parameter-set.json b/parameter-sets/confluence-login/parameter-set.json index 6def833..7bd5bbc 100644 --- a/parameter-sets/confluence-login/parameter-set.json +++ b/parameter-sets/confluence-login/parameter-set.json @@ -27,9 +27,9 @@ }, { "name": "orgname", - "label": "Organization name", + "label": "Subdomain", "type": "STRING", - "description": "", + "description": "First part of your URL: https://.atlassian.net", "visibilityCondition": "model.server_type == 'remote'", "mandatory": false }, diff --git a/plugin.json b/plugin.json index bcd6b75..6afa366 100644 --- a/plugin.json +++ b/plugin.json @@ -1,6 +1,6 @@ { "id": "confluence", - "version": "1.1.1", + "version": "1.1.2", "meta": { "label": "Confluence wiki", "description": "Export a DSS wiki to a Confluence space", @@ -8,7 +8,7 @@ "icon": "icon-cloud-upload", "licenseInfo": "Apache Software License", "url": "https://www.dataiku.com/product/plugins/confluence/", - "tags": ["Governance", "Cloud", "Productivity"], + "tags": ["Business Applications", "Productivity", "Export", "Governance"], "supportLevel": "NOT_SUPPORTED" } } diff --git a/python-lib/md2conf.py b/python-lib/md2conf.py index 7301eb2..78358f6 100644 --- a/python-lib/md2conf.py +++ b/python-lib/md2conf.py @@ -318,8 +318,19 @@ def upload_attachment(page_id, file, comment, confluence_api_url, username, pass session.headers.update({'X-Atlassian-Token': 'no-check'}) res = session.post(url, files=file_to_upload) - - return True + link = None + try: + json_response = res.json() + url_base = json_response.get("_links", {}).get("base", "") + if "results" in json_response: + json_response = json_response.get("results")[0] + link = "{}{}".format( + url_base, + json_response.get("_links", {}).get("download", ""), + ) + except Exception as error: + print("Error {}".format(error)) + return link def urlEncodeNonAscii(b): return re.sub('[\x80-\xFF]', lambda c: '%%%02x' % ord(c.group(0)), b) diff --git a/python-lib/wikitransfer.py b/python-lib/wikitransfer.py index 013ebe3..22eb8bf 100644 --- a/python-lib/wikitransfer.py +++ b/python-lib/wikitransfer.py @@ -31,13 +31,14 @@ def recurse_taxonomy(self, taxonomy, ancestor=None): for article in taxonomy: if len(article['children']) > 0: confluence_id = self.transfer_article(article['id'], ancestor) - self.recurse_taxonomy(article['children'], confluence_id) + self.recurse_taxonomy(article['children'], ancestor=confluence_id) else: - self.transfer_article(article['id'], ancestor) + self.transfer_article(article['id'], parent_id=ancestor) def transfer_article(self, article_id, parent_id=None): self.attachment_table.reset() self.transfered_attachments = [] + self.transfered_links = [] article_data = self.wiki.get_article(article_id).get_data() dss_page_name = article_data.get_name() dss_page_body = article_data.get_body() @@ -90,6 +91,9 @@ def convert(self, md_input, article_id, new_id, article_data): md = md + u'\n' + self.attachment_table.to_md() md = self.convert_math_blocks(md) md = self.develop_dss_links(md) + md = self.develop_image_md_links(md) + md = self.develop_dss_md_links(md) + md = self.develop_md_links(md) html = markdown.markdown(md, extensions=['markdown.extensions.tables', 'markdown.extensions.fenced_code', 'markdown.extensions.nl2br', @@ -164,6 +168,67 @@ def develop_dss_links(self, md): md = re.sub(object_type + r':' + initial_id, self.build_dss_url(object_type, object_path), md, flags=re.IGNORECASE) return md + def develop_md_links(self, md): + # Processing all [name](link) links + links = self.find_md_links(md) + for link in links: + link_name = link[0] + link_target = link[1] + if link_name in self.transfered_attachments: + target_link = self.transfered_links[self.transfered_attachments.index(link_name)] + replacement = '{}'.format(target_link, link_name) + md = md.replace( + "[{}]({})".format(link_name, link_target), + replacement + ) + return md + + def develop_image_md_links(self, md): + # Processing all ![name](link) links + links = self.find_image_md_links(md) + for link in links: + link_name = link[0] + link_target = link[1] + if link_name in self.transfered_attachments: + target_link = self.transfered_links[self.transfered_attachments.index(link_name)] + replacement = '{}'.format(target_link, link_name) + md = md.replace( + "![{}]({})".format(link_name, link_target), + replacement + ) + return md + + def develop_dss_md_links(self, md): + # Processing all [name]{name}(link) links + links = self.find_dss_md_links(md) + for link in links: + link_name = link[0] + link_target = link[1] + link_target_2 = link[2] + if link_name in self.transfered_attachments: + target_link = self.transfered_links[self.transfered_attachments.index(link_name)] + replacement = '{}'.format(target_link, link_name) + md = md.replace( + "[{}]{{{}}}({})".format(link_name, link_target, link_target_2), + replacement + ) + return md + + def find_dss_md_links(self, md): + pattern = r'\[([^\]]+)\]\{([^)]+)\}\(([^)]+)\)' + matches = re.findall(pattern, md) + return matches + + def find_md_links(self, md): + pattern = r'\[([^\]]+)\]\(([^)]+)\)' + matches = re.findall(pattern, md) + return matches + + def find_image_md_links(self, md): + pattern = r'\!\[([^\]]+)\]\(([^)]+)\)' + matches = re.findall(pattern, md) + return matches + def article_title(self, project_key, article_id): name = "" try: @@ -219,8 +284,9 @@ def process_linked_items(self, md, article_id, new_id): try: attachment = self.get_uploaded_file(article, project_id, upload_id) if file_name not in self.transfered_attachments: - upload_attachment(new_id, file_name, "", self.confluence_url, self.confluence_username, self.confluence_password, raw=attachment) + url = upload_attachment(new_id, file_name, "", self.confluence_url, self.confluence_username, self.confluence_password, raw=attachment) self.transfered_attachments.append(file_name) + self.transfered_links.append(url) md = self.replace_md_links_with_confluence_links(md, project_id, upload_id, file_name) except Exception as err: md = self.replace_md_links_with_confluence_links(md, project_id, upload_id, file_name, error_message='*Item could not be transfered*') @@ -288,11 +354,14 @@ def process_attachments(self, article_id, article): for attachment in article.article_data['article']['attachments']: if attachment[u'attachmentType'] == 'FILE' and attachment[u'attachmentType'] not in self.transfered_attachments: attachment_name = attachment['details']['objectDisplayName'] + logger.info("Uploading attachement {} / id: {}".format(attachment_name, attachment['smartId'])) article = self.wiki.get_article(article.article_id) try: file = article.get_uploaded_file(attachment['smartId']) - upload_attachment(article_id, attachment_name, "", self.confluence_url, self.confluence_username, self.confluence_password, raw=file) + url = upload_attachment(article_id, attachment_name, "", self.confluence_url, self.confluence_username, self.confluence_password, raw=file) self.transfered_attachments.append(attachment_name) + self.transfered_links.append(url) + logger.info("Adding {}, {}, {}".format(file, attachment_name, url)) except Exception as err: # get_uploaded_file not implemented yet on backend, older version of DSS logger.info("Attachement could not be uploaded because of older DSS backend:{}".format(err)) diff --git a/python-runnables/export-wiki/runnable.py b/python-runnables/export-wiki/runnable.py index 3a3a8b6..d570a50 100644 --- a/python-runnables/export-wiki/runnable.py +++ b/python-runnables/export-wiki/runnable.py @@ -97,7 +97,7 @@ def run(self, progress_callback): else: self.space_homepage_id = None - self.recurse_taxonomy(self.taxonomy, self.space_homepage_id) + self.recurse_taxonomy(self.taxonomy, ancestor=self.space_homepage_id) if self.space_homepage_id is not None: self.update_landing_page(self.space_homepage_id)