Skip to content

Bug: Code Blocks Rendering as Inline Code in Confluence #65

@FrankLedo

Description

@FrankLedo

Bug Report: Code Blocks Rendering as Inline Code in Confluence

Description

When using @telefonica/markdown-confluence-sync v2.2.0, all fenced code blocks in Markdown files are rendered as inline code (with backticks) instead of proper Confluence code block macros when synced to Confluence.

Expected Behavior

Markdown code blocks should be converted to Confluence's <ac:structured-macro ac:name="code"> storage format with proper language highlighting.

Example Markdown:

```javascript
function hello() {
    console.log("Hello World");
}
```

Expected Confluence Output:

<ac:structured-macro ac:name="code">
  <ac:parameter ac:name="language">javascript</ac:parameter>
  <ac:plain-text-body><![CDATA[function hello() {
    console.log("Hello World");
}]]></ac:plain-text-body>
</ac:structured-macro>

Actual Behavior

Code blocks are rendered as inline code with backticks in the Confluence page body text, losing all formatting and syntax highlighting.

Root Cause

The library's markdown processing pipeline converts markdown → HTML → Confluence storage format:

  • remark plugins process markdown and convert to HTML
  • rehype plugins transform HTML to Confluence storage format

The Issue: The pipeline successfully converts markdown code blocks to HTML <pre><code class="language-x"> tags, but lacks a rehype plugin to convert these HTML elements to Confluence's <ac:structured-macro> format.

File: node_modules/@telefonica/markdown-confluence-sync/dist/lib/confluence/transformer/ConfluencePageTransformer.js

The processing pipeline (lines 52-78) includes plugins for other transformations but is missing a code block converter:

  • rehypeReplaceDetails - converts HTML details/summary
  • rehypeReplaceStrikethrough - converts strikethrough
  • rehypeReplaceTaskList - converts task lists
  • Missing: Plugin to convert <pre><code> to Confluence code macros

Versions Affected

  • @telefonica/markdown-confluence-sync: v2.2.0
  • Tested on: Node.js v22.18.0
  • All programming languages affected (JavaScript, GraphQL, JSON, etc.)

Reproduction

  1. Create a markdown file with a fenced code block:
# Test File

```javascript
console.log("test");
```
  1. Sync to Confluence using the library
  2. Observe that code appears as inline code with backticks instead of a proper code block

Workaround/Fix

We've created a patch that adds the missing rehype plugin:

New file: rehype-confluence-code-blocks.js

// SPDX-FileCopyrightText: 2025 Acoustic, L.P.
// SPDX-License-Identifier: Apache-2.0
import { visit } from 'unist-util-visit';

/**
 * Rehype plugin to convert HTML code blocks to Confluence storage format.
 *
 * Converts:
 *   <pre><code class="language-javascript">code</code></pre>
 *
 * To Confluence storage format:
 *   <ac:structured-macro ac:name="code">
 *     <ac:parameter ac:name="language">javascript</ac:parameter>
 *     <ac:plain-text-body><![CDATA[code]]></ac:plain-text-body>
 *   </ac:structured-macro>
 */
export default function rehypeConfluenceCodeBlocks() {
  return (tree) => {
    visit(tree, 'element', (node, index, parent) => {
      // Look for <pre> elements containing <code>
      if (node.tagName === 'pre' && node.children && node.children.length > 0) {
        const codeNode = node.children[0];

        if (codeNode.type === 'element' && codeNode.tagName === 'code') {
          // Extract language from class (e.g., "language-javascript" -> "javascript")
          let language = '';
          if (codeNode.properties && codeNode.properties.className) {
            const classes = codeNode.properties.className;
            const langClass = classes.find(c => c.startsWith('language-'));
            if (langClass) {
              language = langClass.replace('language-', '');
            }
          }

          // Extract code content
          let code = '';
          const extractText = (node) => {
            if (node.type === 'text') {
              return node.value;
            }
            if (node.children) {
              return node.children.map(extractText).join('');
            }
            return '';
          };
          code = extractText(codeNode);

          // Create Confluence code macro structure
          const confluenceCodeMacro = {
            type: 'element',
            tagName: 'ac:structured-macro',
            properties: {
              'ac:name': 'code',
            },
            children: [],
          };

          // Add language parameter if specified
          if (language) {
            confluenceCodeMacro.children.push({
              type: 'element',
              tagName: 'ac:parameter',
              properties: {
                'ac:name': 'language',
              },
              children: [
                {
                  type: 'text',
                  value: language,
                },
              ],
            });
          }

          // Add code content wrapped in CDATA
          confluenceCodeMacro.children.push({
            type: 'element',
            tagName: 'ac:plain-text-body',
            properties: {},
            children: [
              {
                type: 'raw',
                value: `<![CDATA[${code}]]>`,
              },
            ],
          });

          // Replace the <pre> node with the Confluence macro
          if (parent && typeof index === 'number') {
            parent.children[index] = confluenceCodeMacro;
          }
        }
      }
    });
  };
}

Modification to: ConfluencePageTransformer.js

// Add import at top with other rehype plugins (after line 18)
import rehypeConfluenceCodeBlocks from "./support/rehype/rehype-confluence-code-blocks.js";

// Add to processing pipeline (after line 65, after rehypeReplaceTaskList)
.use(rehypeConfluenceCodeBlocks)

This fix has been tested and confirmed to work correctly, converting all code blocks to proper Confluence code macros with syntax highlighting.

Impact

This bug affects all users trying to sync markdown documentation with code examples to Confluence. Technical documentation, API references, and any content with code snippets will display incorrectly.

Suggested Solution

Add the rehype-confluence-code-blocks plugin (or similar functionality) to the library's default rehype processing pipeline in ConfluencePageTransformer.js.

Environment

  • OS: macOS (Darwin 25.0.0)
  • Node.js: v22.18.0
  • Package version: @telefonica/[email protected]
  • npm: Latest

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions