Skip to content

Comments

fix: BLOCKMENTIONSDATED handles comma dates and 'first of' phrases (#54)#153

Open
salmonumbrella wants to merge 1 commit intoRoamJS:mainfrom
salmonumbrella:issue/54-blockmentionsdated-date-args
Open

fix: BLOCKMENTIONSDATED handles comma dates and 'first of' phrases (#54)#153
salmonumbrella wants to merge 1 commit intoRoamJS:mainfrom
salmonumbrella:issue/54-blockmentionsdated-date-args

Conversation

@salmonumbrella
Copy link
Contributor

@salmonumbrella salmonumbrella commented Feb 18, 2026

Summary

  • parse BLOCKMENTIONSDATED args robustly when dates contain commas
  • normalize 'first of ...' to stable NLP parsing
  • add regression tests for date-token coalescing and malformed refs

Issue

Closes #54

Summary by CodeRabbit

  • New Features

    • Enhanced date handling to support block-mention date formats in date-based computations
  • Improvements

    • Simplified command argument parsing logic for improved reliability and maintainability
  • Tests

    • Added comprehensive test coverage for date parsing and argument tokenization scenarios

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 18, 2026

Walkthrough

This pull request introduces a new utility module for parsing block mention arguments with enhanced date handling. The new splitSmartBlockArgs function parses command arguments while preserving special syntax blocks (percent-delimited commands and double-bracket page references) and applies date coalescence for the BLOCKMENTIONSDATED command type. The core.ts file is refactored to import and use this new utility, replacing previous ad-hoc argument parsing logic. A comprehensive test suite is added to validate tokenization, nesting preservation, and date coalescence behavior.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main fix—BLOCKMENTIONSDATED now handles comma dates and 'first of' phrases, directly addressing the issue.
Linked Issues check ✅ Passed Changes implement date argument parsing (parseBlockMentionsDatedArg), comma-delimited date coalescing (coalesceBlockMentionsDatedDates), and comprehensive tests covering these scenarios as required.
Out of Scope Changes check ✅ Passed All changes are focused on fixing BLOCKMENTIONSDATED date handling via the new splitSmartBlockArgs utility, parseBlockMentionsDatedArg helper, and accompanying tests—no extraneous modifications detected.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


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 and usage tips.

@salmonumbrella
Copy link
Contributor Author

@coderabbitai full review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 18, 2026

✅ Actions performed

Full review triggered.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/utils/core.ts`:
- Around line 133-142: parseBlockMentionsDatedArg currently normalizes "first
of" to "start of" which chrono-node doesn't parse and can return null that later
gets passed into startOfDay/endOfDay; update the parsing and callers by (1)
extending the NLP parser to recognize "start of/beginning of this|next|last
(month|year|week)" (or normalize "start of" to a chrono-friendly phrase like
"beginning of") inside parseNlpDate/addNlpDateParser so phrases like "start of
this month" produce a valid Date, and (2) make callers defensively handle null
by replacing parseBlockMentionsDatedArg(...) with a non-null fallback (e.g.,
parseBlockMentionsDatedArg(startArg, referenceDate) || referenceDate) before
passing into startOfDay/endOfDay; reference symbols: parseBlockMentionsDatedArg,
parseNlpDate, addNlpDateParser, pageTitleToDate, startOfDay, endOfDay.

In `@src/utils/splitSmartBlockArgs.ts`:
- Around line 38-53: The pageRefStack counter is updated even when inside a
command, allowing an unclosed "[[" within a "<%...%>" to leak and block comma
splitting; in the splitSmartBlockArgs logic (variables commandStack,
pageRefStack, afterColon) only increment/decrement pageRefStack when
commandStack === 0 so bracket nesting inside commands is ignored — modify the
branches that handle "[[" and "]]" to check commandStack === 0 before changing
pageRefStack.
- Around line 54-56: The parser drops a leading empty arg because args starts as
[] and the comma handler (inside splitSmartBlockArgs where cur === "," &&
!commandStack && !pageRefStack && prev !== "\\") pushes a new empty slot which
becomes the second arg; to fix, initialize args with a single empty string (args
= [""]) before the main parsing loop (or at start of parsing for the afterColon
segment) so a leading comma produces ["","..."] as intended; leave the existing
comma handler and other logic intact but ensure any code that reinitializes args
preserves the initial [""] seed.

In `@tests/splitSmartBlockArgs.test.ts`:
- Around line 4-75: Add four unit tests for splitSmartBlockArgs to cover the
missing edge cases: (1) an empty afterColon argument ("") should assert []
instead of [""], (2) an escaped comma input like "a\\,b" should return ["a,b"]
to exercise the backslash-escape branch, (3) a leading comma input like ",title"
should assert ["", "title"] (or the expected behavior your implementation
intends) to catch the first-arg-drop bug, and (4) a balanced page ref with an
internal comma and a trailing year token like "[[January 1st, 2023]],2023"
should verify that the page ref remains a single token ("[[January 1st, 2023]]")
and the year stays separate; add these tests alongside the existing ones
referencing splitSmartBlockArgs so they run in the same suite.
- Around line 43-57: The test for "coalesces at most two date tokens for
BLOCKMENTIONSDATED" currently expects a final token of " 2023" (with a leading
space) because coalesceBlockMentionsDatedDates stops after mergedDates === 2 and
forwards the untrimmed remaining token as the format argument; add a short
inline comment in the test (near the expect or the tokens array) explaining that
the leading space is intentional and results from the third date not being
coalesced so future readers won't treat " 2023" as a typo — reference the test
name and the splitSmartBlockArgs call so it's clear which behavior is being
documented.

Comment on lines +133 to +142
const parseBlockMentionsDatedArg = (dateArg: string, referenceDate: Date) => {
const normalizedArg = dateArg.trim().replace(/^first of\b/i, "start of");
const title =
DAILY_REF_REGEX.exec(normalizedArg)?.[1] ||
DAILY_NOTE_PAGE_TITLE_REGEX.exec(extractTag(normalizedArg))?.[0];
return title
? window.roamAlphaAPI.util.pageTitleToDate(title) ||
parseNlpDate(normalizedArg, referenceDate)
: parseNlpDate(normalizedArg, referenceDate);
};
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

date-fns startOfDay null behavior JavaScript

💡 Result:

In date-fns, startOfDay calls toDate first, then does setHours(0,0,0,0). (app.unpkg.com)

What happens if you pass null?

It depends on the date-fns major version:

  • date-fns v2 (and the v2-era design): null is treated as not a valid date, so toDate(null) returns Invalid Date, and therefore startOfDay(null) also yields an invalid date value. (blog.date-fns.org)

  • date-fns v4.1.0 (current “latest” on unpkg at the time of this lookup): toDate(null) ends up doing new Date(null) via constructFrom(...), which produces a valid Date at Unix epoch (timestamp 0), so startOfDay(null) returns the start of 1970-01-01 in the local timezone. (app.unpkg.com)

Practical takeaway

Don’t rely on null coercion—guard it yourself (or validate with isValid) before calling startOfDay, because the runtime behavior has differed across major versions. (app.unpkg.com)

Citations:


🌐 Web query:

chrono-node "start of this month" natural language parsing

💡 Result:

chrono-node doesn’t have a built-in concept like “start of this month” (i.e., normalize to day 1 @ 00:00), but it’s designed to be extended: you can clone a parser (e.g. chrono.casual.clone()) and push a custom parser (or a refiner) to recognize that phrase and return the components you want. (npmjs.com)

Option A: Add a custom parser for “start of this month”

import * as chrono from "chrono-node";

const custom = chrono.casual.clone();

custom.parsers.push({
  pattern: () => /\bstart of (this|current) month\b/i,
  extract: (context, match) => {
    const ref = context.refDate; // the reference date chrono is parsing relative to
    return {
      year: ref.getFullYear(),
      month: ref.getMonth() + 1, // chrono months are 1-12
      day: 1,
      hour: 0,
      minute: 0,
      second: 0,
      millisecond: 0,
    };
  },
});

const d = custom.parseDate("start of this month"); // -> Date at local 00:00 on the 1st

This follows chrono’s documented extension pattern (clone + parsers.push(...)). (npmjs.com)

Option B: Parse “this month”, then post-process

If you’re okay with post-processing, parse something like "this month" and then set the returned Date to the 1st at midnight in your own code (using JS new Date(y, m, 1)), rather than teaching chrono the phrase. (Chrono exposes parseDate / parse and ParsedComponents.date() to get a Date you can adjust.) (npmjs.com)

Citations:


🏁 Script executed:

cat -n src/utils/core.ts | sed -n '1230,1240p'

Repository: RoamJS/smartblocks

Length of output: 619


🏁 Script executed:

grep -n "const parseNlpDate" src/utils/core.ts -A 10

Repository: RoamJS/smartblocks

Length of output: 44


🏁 Script executed:

cat package.json | grep -A 2 -B 2 '"date-fns"'

Repository: RoamJS/smartblocks

Length of output: 44


🏁 Script executed:

rg "parseNlpDate" src/utils/core.ts -A 5 -B 2

Repository: RoamJS/smartblocks

Length of output: 5975


🏁 Script executed:

fd package.json

Repository: RoamJS/smartblocks

Length of output: 74


🏁 Script executed:

rg "date-fns" package.json

Repository: RoamJS/smartblocks

Length of output: 44


🏁 Script executed:

rg "addNlpDateParser" src/utils/core.ts

Repository: RoamJS/smartblocks

Length of output: 100


🏁 Script executed:

head -50 package.json

Repository: RoamJS/smartblocks

Length of output: 835


🏁 Script executed:

rg "addNlpDateParser" src/utils/core.ts -A 20 -B 2

Repository: RoamJS/smartblocks

Length of output: 1824


🏁 Script executed:

rg "addNlpDateParser" src/utils/core.ts -A 50 | head -100

Repository: RoamJS/smartblocks

Length of output: 3272


parseBlockMentionsDatedArg returns null when date parsing fails, and the "first of" → "start of" normalization is unsupported.

1. Missing "start of" parser: Line 137 replaces "first of" → "start of" (e.g., "first of this month" becomes "start of this month"), but chrono-node has no built-in parser for "start of" phrases. The custom parser added via addNlpDateParser only handles the DBOM/DEOM format, not natural language "start of" expressions. This means the normalized phrase will fail to parse, and parseNlpDate will return null.

2. Null propagation into startOfDay/endOfDay: When pageTitleToDate and parseNlpDate both fail, parseBlockMentionsDatedArg returns null. The guards at lines 1233 and 1237 check if startArg and endArg are truthy, but they do not guard the return value of parseBlockMentionsDatedArg. A null result propagates directly into startOfDay(null) and endOfDay(null). In date-fns v4, new Date(null) coerces to Unix epoch (1970-01-01), which will silently filter results to that date instead of failing loudly.

Fixes:

  • Add a custom NLP parser for "start of this month/year/week" patterns, or adjust the normalization to a phrase chrono-node understands (e.g., "beginning of this month").
  • Guard the return value: parseBlockMentionsDatedArg(startArg, referenceDate) || new Date() before passing to startOfDay/endOfDay.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/utils/core.ts` around lines 133 - 142, parseBlockMentionsDatedArg
currently normalizes "first of" to "start of" which chrono-node doesn't parse
and can return null that later gets passed into startOfDay/endOfDay; update the
parsing and callers by (1) extending the NLP parser to recognize "start
of/beginning of this|next|last (month|year|week)" (or normalize "start of" to a
chrono-friendly phrase like "beginning of") inside parseNlpDate/addNlpDateParser
so phrases like "start of this month" produce a valid Date, and (2) make callers
defensively handle null by replacing parseBlockMentionsDatedArg(...) with a
non-null fallback (e.g., parseBlockMentionsDatedArg(startArg, referenceDate) ||
referenceDate) before passing into startOfDay/endOfDay; reference symbols:
parseBlockMentionsDatedArg, parseNlpDate, addNlpDateParser, pageTitleToDate,
startOfDay, endOfDay.

Comment on lines +38 to +53
let commandStack = 0;
let pageRefStack = 0;
const args = [] as string[];
for (let i = 0; i < afterColon.length; i += 1) {
const cur = afterColon[i];
const prev = afterColon[i - 1];
const next = afterColon[i + 1];
if (cur === "%" && prev === "<") {
commandStack += 1;
} else if (cur === "%" && next === ">" && commandStack) {
commandStack -= 1;
} else if (cur === "[" && next === "[") {
pageRefStack += 1;
} else if (cur === "]" && prev === "]" && pageRefStack) {
pageRefStack -= 1;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

pageRefStack can leak past a <%...%> command boundary when the command contains an unclosed [[.

The else if chain updates pageRefStack regardless of commandStack, meaning an unclosed [[ inside a nested command leaves pageRefStack > 0 after commandStack returns to zero. Any comma that follows the nested command will then be swallowed instead of acting as an argument separator.

Concrete trace for afterColon = "<%CMD:[[page%>,nextArg":

  • <%commandStack = 1
  • [[pageRefStack = 1 ← happens even while commandStack > 0
  • %>commandStack = 0; pageRefStack stays at 1
  • , → not split (pageRefStack = 1)
  • Result: ["<%CMD:[[page%>,nextArg"] instead of ["<%CMD:[[page%>", "nextArg"]

This only triggers on malformed input, but the fix is straightforward — only modify pageRefStack when commandStack === 0:

🛡️ Proposed fix
    if (cur === "%" && prev === "<") {
      commandStack += 1;
    } else if (cur === "%" && next === ">" && commandStack) {
      commandStack -= 1;
-   } else if (cur === "[" && next === "[") {
-     pageRefStack += 1;
-   } else if (cur === "]" && prev === "]" && pageRefStack) {
-     pageRefStack -= 1;
+   } else if (!commandStack) {
+     if (cur === "[" && next === "[") {
+       pageRefStack += 1;
+     } else if (cur === "]" && prev === "]" && pageRefStack) {
+       pageRefStack -= 1;
+     }
    }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
let commandStack = 0;
let pageRefStack = 0;
const args = [] as string[];
for (let i = 0; i < afterColon.length; i += 1) {
const cur = afterColon[i];
const prev = afterColon[i - 1];
const next = afterColon[i + 1];
if (cur === "%" && prev === "<") {
commandStack += 1;
} else if (cur === "%" && next === ">" && commandStack) {
commandStack -= 1;
} else if (cur === "[" && next === "[") {
pageRefStack += 1;
} else if (cur === "]" && prev === "]" && pageRefStack) {
pageRefStack -= 1;
}
let commandStack = 0;
let pageRefStack = 0;
const args = [] as string[];
for (let i = 0; i < afterColon.length; i += 1) {
const cur = afterColon[i];
const prev = afterColon[i - 1];
const next = afterColon[i + 1];
if (cur === "%" && prev === "<") {
commandStack += 1;
} else if (cur === "%" && next === ">" && commandStack) {
commandStack -= 1;
} else if (!commandStack) {
if (cur === "[" && next === "[") {
pageRefStack += 1;
} else if (cur === "]" && prev === "]" && pageRefStack) {
pageRefStack -= 1;
}
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/utils/splitSmartBlockArgs.ts` around lines 38 - 53, The pageRefStack
counter is updated even when inside a command, allowing an unclosed "[[" within
a "<%...%>" to leak and block comma splitting; in the splitSmartBlockArgs logic
(variables commandStack, pageRefStack, afterColon) only increment/decrement
pageRefStack when commandStack === 0 so bracket nesting inside commands is
ignored — modify the branches that handle "[[" and "]]" to check commandStack
=== 0 before changing pageRefStack.

Comment on lines +54 to +56
if (cur === "," && !commandStack && !pageRefStack && prev !== "\\") {
args.push("");
continue;
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Leading comma silently drops the first argument slot.

args is initialized as []. When afterColon begins with ,, args.push("") (the handler for a comma) pushes the only element, but it represents the second argument's slot, not the first. The subsequent character then fills args[0], permanently losing the first empty argument.

afterColon = ",title" → ["title"]  // expects ["", "title"]

For BLOCKMENTIONSDATED this shifts every positional arg left by one (titlelimit, startDatetitle, …).

🛡️ Proposed fix
    if (cur === "," && !commandStack && !pageRefStack && prev !== "\\") {
+     if (!args.length) args.push(""); // ensure first arg slot exists
      args.push("");
      continue;
    }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (cur === "," && !commandStack && !pageRefStack && prev !== "\\") {
args.push("");
continue;
if (cur === "," && !commandStack && !pageRefStack && prev !== "\\") {
if (!args.length) args.push(""); // ensure first arg slot exists
args.push("");
continue;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/utils/splitSmartBlockArgs.ts` around lines 54 - 56, The parser drops a
leading empty arg because args starts as [] and the comma handler (inside
splitSmartBlockArgs where cur === "," && !commandStack && !pageRefStack && prev
!== "\\") pushes a new empty slot which becomes the second arg; to fix,
initialize args with a single empty string (args = [""]) before the main parsing
loop (or at start of parsing for the afterColon segment) so a leading comma
produces ["","..."] as intended; leave the existing comma handler and other
logic intact but ensure any code that reinitializes args preserves the initial
[""] seed.

Comment on lines +4 to +75
test("splits nested smartblock commands as a single argument", () => {
expect(
splitSmartBlockArgs("ANYCOMMAND", "one,<%RANDOMNUMBER:1,10%>,two")
).toEqual(["one", "<%RANDOMNUMBER:1,10%>", "two"]);
});

test("preserves commas in daily note page references", () => {
expect(
splitSmartBlockArgs(
"BLOCKMENTIONSDATED",
"10,DONE,[[January 24th, 2023]],[[January 1st, 2023]]"
)
).toEqual(["10", "DONE", "[[January 24th, 2023]]", "[[January 1st, 2023]]"]);
});

test("coalesces month-day-year date tokens for BLOCKMENTIONSDATED", () => {
expect(
splitSmartBlockArgs(
"BLOCKMENTIONSDATED",
"10,DONE,February 1, 2023,February 24, 2023,DESC"
)
).toEqual(["10", "DONE", "February 1, 2023", "February 24, 2023", "DESC"]);
});

test("handles unclosed [[ gracefully by treating rest as single arg", () => {
expect(
splitSmartBlockArgs("BLOCKMENTIONSDATED", "10,DONE,[[January 24th")
).toEqual(["10", "DONE", "[[January 24th"]);
});

test("preserves commas inside nested page references", () => {
expect(
splitSmartBlockArgs(
"BLOCKMENTIONSDATED",
"10,DONE,[[January 24th, 2023]],today"
)
).toEqual(["10", "DONE", "[[January 24th, 2023]]", "today"]);
});

test("coalesces at most two date tokens for BLOCKMENTIONSDATED", () => {
expect(
splitSmartBlockArgs(
"BLOCKMENTIONSDATED",
"10,DONE,January 1, 2023,February 1, 2023,March 1, 2023"
)
).toEqual([
"10",
"DONE",
"January 1, 2023",
"February 1, 2023",
"March 1",
" 2023",
]);
});

test("does not coalesce date tokens for non-BLOCKMENTIONSDATED commands", () => {
expect(
splitSmartBlockArgs("ANYCOMMAND", "January 1, 2023")
).toEqual(["January 1", " 2023"]);
});

test("unclosed [[ in non-BLOCKMENTIONSDATED treats remaining as single arg", () => {
expect(
splitSmartBlockArgs("ANYCOMMAND", "one,[[unclosed,two,three")
).toEqual(["one", "[[unclosed,two,three"]);
});

test("balanced [[ ]] followed by normal args splits correctly", () => {
expect(
splitSmartBlockArgs("ANYCOMMAND", "[[page ref]],normal,arg")
).toEqual(["[[page ref]]", "normal", "arg"]);
});
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Missing edge-case test coverage.

The suite covers the happy paths well, but several boundary conditions are absent:

Scenario Why it matters
Empty afterColon ("") Should return []; verifies the caller doesn't receive [""]
Escaped comma ("a\\,b") The backslash-escape path at lines 57–58 of splitSmartBlockArgs.ts is untested
Leading comma (",title") Exercises the known first-arg-drop bug (see related comment on splitSmartBlockArgs.ts)
Balanced [[...]] with comma inside and trailing year token Ensures [[January 1st, 2023]] is not coalesced when it's already one token (the coalescence regex only matches bare "Month Day")

Would you like me to draft the missing test cases?

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/splitSmartBlockArgs.test.ts` around lines 4 - 75, Add four unit tests
for splitSmartBlockArgs to cover the missing edge cases: (1) an empty afterColon
argument ("") should assert [] instead of [""], (2) an escaped comma input like
"a\\,b" should return ["a,b"] to exercise the backslash-escape branch, (3) a
leading comma input like ",title" should assert ["", "title"] (or the expected
behavior your implementation intends) to catch the first-arg-drop bug, and (4) a
balanced page ref with an internal comma and a trailing year token like
"[[January 1st, 2023]],2023" should verify that the page ref remains a single
token ("[[January 1st, 2023]]") and the year stays separate; add these tests
alongside the existing ones referencing splitSmartBlockArgs so they run in the
same suite.

Comment on lines +43 to +57
test("coalesces at most two date tokens for BLOCKMENTIONSDATED", () => {
expect(
splitSmartBlockArgs(
"BLOCKMENTIONSDATED",
"10,DONE,January 1, 2023,February 1, 2023,March 1, 2023"
)
).toEqual([
"10",
"DONE",
"January 1, 2023",
"February 1, 2023",
"March 1",
" 2023",
]);
});
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Third-date coalescence limit behavior is correctly documented, but the " 2023" leading space deserves a comment.

The test asserts " 2023" (with leading space) as the 6th token when a third date is supplied. This is technically correct — coalesceBlockMentionsDatedDates stops after mergedDates === 2 and passes the raw, un-trimmed " 2023" token as the format argument of BLOCKMENTIONSDATED. Adding an inline comment makes the intent explicit so future readers don't mistake the leading space for a typo:

💡 Suggested comment
  ).toEqual([
    "10",
    "DONE",
    "January 1, 2023",
    "February 1, 2023",
-   "March 1",
-   " 2023",
+   "March 1",   // mergedDates === 2, so 3rd date is not coalesced...
+   " 2023",     // ...and the raw " 2023" token retains its leading space
  ]);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
test("coalesces at most two date tokens for BLOCKMENTIONSDATED", () => {
expect(
splitSmartBlockArgs(
"BLOCKMENTIONSDATED",
"10,DONE,January 1, 2023,February 1, 2023,March 1, 2023"
)
).toEqual([
"10",
"DONE",
"January 1, 2023",
"February 1, 2023",
"March 1",
" 2023",
]);
});
test("coalesces at most two date tokens for BLOCKMENTIONSDATED", () => {
expect(
splitSmartBlockArgs(
"BLOCKMENTIONSDATED",
"10,DONE,January 1, 2023,February 1, 2023,March 1, 2023"
)
).toEqual([
"10",
"DONE",
"January 1, 2023",
"February 1, 2023",
"March 1", // mergedDates === 2, so 3rd date is not coalesced...
" 2023", // ...and the raw " 2023" token retains its leading space
]);
});
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/splitSmartBlockArgs.test.ts` around lines 43 - 57, The test for
"coalesces at most two date tokens for BLOCKMENTIONSDATED" currently expects a
final token of " 2023" (with a leading space) because
coalesceBlockMentionsDatedDates stops after mergedDates === 2 and forwards the
untrimmed remaining token as the format argument; add a short inline comment in
the test (near the expect or the tokens array) explaining that the leading space
is intentional and results from the third date not being coalesced so future
readers won't treat " 2023" as a typo — reference the test name and the
splitSmartBlockArgs call so it's clear which behavior is being documented.

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.

BLOCKMENTIONSDATED commands fail to handle Roam Dates and "first of this month"

1 participant