Skip to content

Roam: Fix table conversion and code block formatting#506

Open
cristip73 wants to merge 2 commits intoobsidianmd:masterfrom
cristip73:fix/roam-tables-and-codeblocks
Open

Roam: Fix table conversion and code block formatting#506
cristip73 wants to merge 2 commits intoobsidianmd:masterfrom
cristip73:fix/roam-tables-and-codeblocks

Conversation

@cristip73
Copy link
Copy Markdown

Summary

Two improvements to the Roam Research JSON importer:

1. Convert {{[[table]]}} blocks to native Markdown pipe tables

Roam tables were previously left as raw text (the conversion code was commented out). This implements proper structural conversion:

  • Detects {{[[table]]}} / {{table}} blocks in the JSON tree (not via string replacement)
  • Extracts cells by walking each row's linear first-child chain (supports any number of columns)
  • First row becomes headers, remaining rows become data
  • Pads uneven rows with empty cells
  • Escapes pipe characters in cell content
  • Runs each cell through roamMarkupScrubber() for proper link/markup conversion

Before: Tables imported as nested bullet lists (unusable)
After: Clean Markdown pipe tables that render natively in Obsidian

2. Fix code block formatting inside bullet lists

Multi-line code blocks (stored with \n in Roam's block string) lost their indentation during import, breaking the bullet hierarchy in Obsidian. Everything after an opening ``` would be swallowed into a single giant code block.

Three fixes:

  • Indent continuation lines of multi-line blocks to align with the bullet content level
  • Normalize code fences so opening/closing ``` are always on separate lines (Roam exports them glued to content)
  • Strip Roam language tags (javascript, python, etc.) from code fences — Roam uses these internally but they cause rendering issues in Obsidian's list context

Before: Code blocks break bullet hierarchy, all content below absorbed into code
After: Properly contained code blocks with correct bullet nesting

Test plan

  • Import a Roam JSON export containing {{[[table]]}} blocks — verify pipe tables render correctly
  • Import a Roam JSON with code blocks (single-line and multi-line) — verify bullets after code blocks are not absorbed
  • Verify tables with uneven columns pad correctly
  • Verify code blocks with language tags (javascript, python) have tags stripped
  • Verify regular (non-code-block) multi-line blocks maintain proper indentation
  • Run npm run build and npm run lint — both pass

🤖 Generated with Claude Code

cristip73 and others added 2 commits February 23, 2026 12:55
Previously table markers were stripped (commented-out code) and table
children rendered as plain bullet lists. This adds proper structural
conversion: each row's linear first-child chain becomes table columns,
with Roam markup scrubbed, pipes escaped, and uneven rows padded.

Also adds CLAUDE.md and gitignores _DOCS/_gpt5_docs local dirs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Multi-line code blocks in Roam blocks (stored with \n in the string
field) lost their indentation during import, breaking the bullet
hierarchy in Obsidian. Three fixes:

- Indent continuation lines of multi-line blocks to align with the
  bullet content level
- Normalize code fences so opening/closing ``` are on separate lines
- Strip Roam language tags (```javascript, ```python, etc.) from
  code fences since they cause rendering issues in list context

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@tgrosinger
Copy link
Copy Markdown
Contributor

This PR duplicates a commit from #505. Please remove that commit from this PR so they can be reviewed and merged independently.


private async roamMarkupScrubber(graphFolder: string, attachmentsFolder: string, blockText: string, skipDownload: boolean = false): Promise<string> {
// Strip language tags from code blocks (```javascript\n → ```\n)
blockText = blockText.replace(codeBlockLangRe, '```\n');
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are these being stripped? Obsidian supports these.

const linePrefix = isChild ? indent + '* ' : indent;
const continuationIndent = isChild ? indent + ' ' : indent;
const indented = scrubbed.contains('\n')
? scrubbed.split('\n').map((line, i) => i === 0 ? line : continuationIndent + line).join('\n')
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should avoid prepending whitespace to blank lines. You also don't need to the check for newlines.

const indented = scrubbed
    .split('\n')
    .map((line, i) => (i === 0 || line === '') ? line : continuationIndent + line)
    .join('\n');


const blockRefRegex = /(?<=\(\()\b(.*?)\b(?=\)\))/g;
const roamTableRe = /^\{\{(\[\[)?table(\]\])?\}\}$/i;
const codeBlockLangs = ['clojure', 'css', 'elixir', 'html', 'plain text', 'python', 'ruby', 'swift', 'typescript', 'jsx', 'yaml', 'json', 'json-ld', 'rust', 'r', 'shell', 'php', 'java', 'c#', 'c', 'c\\+\\+', 'objective-c', 'go', 'kotlin', 'sql', 'haskell', 'scala', 'commonlisp', 'solidity', 'julia', 'sparql', 'turtle', 'lua', 'dart', 'latex', 'markdown', 'xml', 'toml', 'vb', 'vbscript', 'javascript'];
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm confused why this is needed. Why are these tags being removed?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants