Skip to content

Resolve raw Roam UIDs and block references in Manage - #12

Closed
mdroidian wants to merge 1 commit into
mainfrom
codex/support-roam-uid-formats-pr
Closed

Resolve raw Roam UIDs and block references in Manage#12
mdroidian wants to merge 1 commit into
mainfrom
codex/support-roam-uid-formats-pr

Conversation

@mdroidian

@mdroidian mdroidian commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Support raw Roam UIDs and ((block reference)) inputs in Manage.
  • Resolve direct UID searches before running text search.
  • Add parsing and direct-resolution test coverage.
  • Update the changelog.

Testing

  • Added unit coverage for raw and block-reference UID parsing and resolution.

Open in Devin Review

@coderabbitai

coderabbitai Bot commented Aug 17, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 08abfd4b-da86-4559-8aeb-bddf1051c27d

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Devin Review found 2 potential issues.

View 1 additional finding in Devin Review.

Open in Devin Review

Comment on lines +90 to +93
parseRoamUid({ value: normalizedValue }) ||
(isPageUrlInput({ entry: normalizedValue })
? parsePageUidFromUrl({ url: normalizedValue })
: normalizedValue) ||
: null) ||

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Adding an entry by a custom-length Roam ID or block reference no longer works

Inputs are now only accepted as IDs when they are exactly 9-10 characters long (ROAM_UID_REGEX at src/utils/quickSwitcher.ts:11 combined with the imported reference pattern), so entries whose ID has a different length can no longer be added by pasting the ID or its reference.
Impact: Users with custom (non 9-10 character) Roam identifiers get "No page or block matched that input" for inputs that previously worked.

How the stricter ID validation removes previously working paths

Before this change, getUidFromEntryInput (src/utils/quickSwitcherEntries.ts:87-96) returned the raw trimmed input for any non-URL text, so resolveEntryInput (src/utils/quickSwitcherEntries.ts:406-412) would attempt a direct UID lookup for arbitrary-length IDs, and the old local BLOCK_REF_REGEX (/\(\(([A-Za-z0-9_-]+)\)\)/) matched block references of any length.

Now the non-URL branch returns null unless parseRoamUid matches, and parseRoamUid only accepts ^[\w-]{9,10}$ or the roamjs-components BLOCK_REF_REGEX, which is /\(\(([\w\d-]{9,10})\)\)/. Roam allows user-specified custom block/page UIDs of other lengths (e.g. ((my-custom-uid))), which now fall through to resolvePageTitleToSuggestion (src/utils/quickSwitcherEntries.ts:376-393) with the literal text and fail.

Prompt for agents
parseRoamUid in src/utils/quickSwitcher.ts restricts identifiers to 9-10 characters (ROAM_UID_REGEX) and the newly imported roamjs-components BLOCK_REF_REGEX also enforces {9,10}. Combined with getUidFromEntryInput in src/utils/quickSwitcherEntries.ts now returning null instead of the raw input for non-URL text, custom Roam UIDs of other lengths (which users can set explicitly, and which previously resolved through resolveEntryInput) can no longer be added. Consider keeping a permissive fallback for the explicit add path (resolveEntryInput): e.g. still attempt a direct UID lookup with the raw input when strict parsing fails, or relax the block-reference pattern to accept any [\w-]+ inside the double parens while keeping the strict pattern for the live search short-circuit.
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +248 to +259
const directUid = getUidFromEntryInput({ value: query });
if (directUid) {
const directSuggestion = await resolveUidToSuggestion({ uid: directUid });
if (
directSuggestion &&
!savedTargetKeys.has(
getSuggestionTargetKey({ suggestion: directSuggestion }),
)
) {
return [directSuggestion];
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Blocks found by pasting an ID are saved without their parent trail

A block found directly from a pasted identifier is returned immediately (return [directSuggestion] at src/utils/quickSwitcherEntries.ts:257) without collecting its parent trail, so it is shown and saved without the page/parent context that normal search results include.
Impact: Entries added by pasting a block identifier appear without their page and parent context, unlike identical entries added via text search.

Breadcrumb enrichment is skipped on the direct path

The text-search path ends with addBreadcrumbsToBlockSuggestions({ suggestions }) (src/utils/quickSwitcherEntries.ts:319), which pulls :block/page / :block/parents per block suggestion and attaches breadcrumbs. The new early return at src/utils/quickSwitcherEntries.ts:248-259 skips that step entirely, and createBookmarkFromSuggestion (src/utils/quickSwitcherEntries.ts:145-159) only stores breadcrumbs when the suggestion carries them, so the persisted bookmark permanently lacks the trail.

Suggested change
const directUid = getUidFromEntryInput({ value: query });
if (directUid) {
const directSuggestion = await resolveUidToSuggestion({ uid: directUid });
if (
directSuggestion &&
!savedTargetKeys.has(
getSuggestionTargetKey({ suggestion: directSuggestion }),
)
) {
return [directSuggestion];
}
}
const directUid = getUidFromEntryInput({ value: query });
if (directUid) {
const directSuggestion = await resolveUidToSuggestion({ uid: directUid });
if (
directSuggestion &&
!savedTargetKeys.has(
getSuggestionTargetKey({ suggestion: directSuggestion }),
)
) {
return addBreadcrumbsToBlockSuggestions({
suggestions: [directSuggestion],
});
}
}
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: dca60bba29

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

QuickSwitcherCommandPaletteSettings,
QuickSwitcherTargetType,
} from "~/types/quickSwitcher";
import { BLOCK_REF_REGEX } from "roamjs-components/dom/constants";

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Preserve the block-reference capture group

The imported BLOCK_REF_REGEX is global, so value.match(BLOCK_REF_REGEX) returns only complete matches rather than capture groups. For a single input such as ((acW-i9uMD)), match[1] is therefore undefined, causing parseRoamUid to return null and preventing the new direct-resolution path; with multiple references it can even return the second full reference as the UID. Use a non-global regex or extract the capture with an appropriate exec/match-all strategy.

Useful? React with 👍 / 👎.

@mdroidian mdroidian closed this Aug 17, 2026
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.

1 participant