Skip to content

feat(doc): warn when callout uses type= without background-color#467

Merged
fangshuyu-768 merged 4 commits intomainfrom
feat/callout-type-to-color
Apr 30, 2026
Merged

feat(doc): warn when callout uses type= without background-color#467
fangshuyu-768 merged 4 commits intomainfrom
feat/callout-type-to-color

Conversation

@herbertliu
Copy link
Copy Markdown
Collaborator

@herbertliu herbertliu commented Apr 14, 2026

Summary

When a user writes <callout type="warning" emoji="📝"> in markdown passed to docs +create / docs +update, the Feishu side renders the callout block with no colortype= is a semantic shorthand the create-doc API does not consume; it only understands background-color= / border-color=.

This PR is a diagnostic, not a renderer fix: it does not rewrite the markdown. Instead it scans the input and, when type= is used without an explicit background-color=, prints one hint line on stderr telling the user exactly which color attributes to write to get the color they probably wanted. The next manual edit fixes the document; the markdown reaching the API is byte-identical to what the user passed.

After review by @SunPeiYang996 the original approach (silently expanding type= into the matching color pair inside the shortcut) was rejected as protocol-adaptation logic in the wrong layer. The hint-on-stderr design adopted here is option 3 of his suggested alternatives.

Behavior

$ lark-cli docs +create --markdown '<callout type="warning">x</callout>'
hint: callout type="warning" has no background-color; consider: background-color="light-yellow" border-color="yellow"
{
  "ok": true,
  ...
}
  • Markdown reaching create-doc is unmodified.
  • Stdout JSON envelope, exit code, and dry-run renderer are all unchanged.
  • Feishu rendering is unchanged from the pre-PR baseline (colorless callout); the user has to follow the hint and rewrite to get color. The PR's value is turning a silent failure into an actionable, copy-pasteable suggestion.

Changes

  • shortcuts/doc/markdown_fix.go — add WarnCalloutType(md, w io.Writer). Fence-aware line walker that scans <callout …> opening tags; for each tag with a recognized type= but no background-color=, writes one hint line to w. Read-only; markdown is never modified.
  • shortcuts/doc/docs_create.go / shortcuts/doc/docs_update.go — invoke WarnCalloutType(runtime.Str("markdown"), runtime.IO().ErrOut) from the v1 Execute path, immediately before the API call. v2 and --dry-run paths are intentionally not wired (out of scope; can be revisited if/when the same pattern proves useful there).
  • shortcuts/doc/markdown_fix_test.go — 14 TestWarnCalloutType subtests covering emits-hint, suppression, fence skipping, attribute-prefix isolation, and regressions for false positives.

Robustness (review fixes from @fangshuyu-768)

  • Regex anchors (?:^|\s)type= and (?:^|\s)background-color\s*= — replace \b. \b sits at any word/non-word boundary, and - is a non-word character, so \btype= also matches the suffix of data-type=. Result before fix: <callout data-type="warning"> would emit a phantom light-yellow hint, and a future data-background-color= attribute would silently suppress the real hint. The new anchor requires a real attribute separator.
  • Code fences skipped. Walks lines and tracks fence state via the existing codeFenceOpenMarker / isCodeFenceClose helpers (CommonMark §4.5, both ``` and ~~~). A documentation sample inside a fenced block no longer produces a phantom hint.
  • scanCalloutTagsForWarning extracted as a FindAllStringSubmatch-based per-line scanner. Replaces the prior ReplaceAllStringFunc-as-iterator pattern (rebuilt string was discarded; a second regex execution inside the callback recovered the capture groups). Same observable behavior, half the work.
  • Whitespace around = toleratedbackground-color = "..." is recognized as a present attribute, same as background-color="...".

type → suggested color (advisory mapping used in hint text)

type background-color border-color
warning light-yellow yellow
info / note light-blue blue
tip / success / check light-green green
error / danger light-red red
caution light-orange orange
important light-purple purple

This mapping is the CLI's own convention and is used only to compose the hint string. The markdown is never modified, so callers and downstream MCP clients are not asked to know or replicate the mapping.

Test Plan

  • go test ./shortcuts/doc/... — 14 TestWarnCalloutType cases pass (incl. 5 review-driven regressions: data-type not triggering, data-background-color not suppressing, backtick fence skip, tilde fence skip, fence-state reset)
  • go test -race ./shortcuts/doc/... — clean
  • go vet ./... clean
  • gofmt -l . clean
  • golangci-lint run --new-from-rev=origin/main — 0 issues
  • Skill format check passes
  • Full unit suite (go test $(go list ./... | grep -v cli_e2e) -count=1) — all packages green
  • Docs e2e (go test ./tests/cli_e2e/docs/...) — passes

Out of scope / follow-up

  • Native type= support inside create-doc would obsolete this hint entirely; that is option 1 of @SunPeiYang996's review and the right long-term fix.
  • Wiring WarnCalloutType into the v2 path or into --dry-run is a small follow-up if the diagnostic proves useful.

Copy link
Copy Markdown

@greptile-apps greptile-apps Bot left a comment

Choose a reason for hiding this comment

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

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

@github-actions github-actions Bot added domain/ccm PR touches the ccm domain size/M Single-domain feat or fix with limited business impact labels Apr 14, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 14, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds WarnCalloutType(md string, w io.Writer) to scan Markdown for <callout> tags missing background-color and emit hint lines to stderr; calls to this helper were inserted into docs create/update flows when --markdown is present. Unit tests for the helper were added.

Changes

Cohort / File(s) Summary
Callout warning utility
shortcuts/doc/markdown_fix.go, shortcuts/doc/markdown_fix_test.go
Add WarnCalloutType that scans Markdown (skips fenced code blocks), detects <callout> tags with type=... but missing background-color=..., maps known type → suggested background-color/border-color, and emits hint lines; add TestWarnCalloutType.
Docs create integration
shortcuts/doc/docs_create.go
buildDocsCreateArgs now assigns md := runtime.Str("markdown"), calls WarnCalloutType(md, runtime.IO().ErrOut), and uses md for the markdown arg.
Docs update integration
shortcuts/doc/docs_update.go
DocsUpdate.DryRun and DocsUpdate.Execute call WarnCalloutType(v, runtime.IO().ErrOut) when the --markdown value is non-empty before setting args["markdown"].

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant CLI as "CLI runtime"
  participant Warn as "WarnCalloutType\n(hint writer -> stderr)"
  participant MCP as "MCP create-doc / update-doc"

  User->>CLI: invoke docs create/update with --markdown
  CLI->>Warn: WarnCalloutType(markdown, stderr)
  Warn-->>CLI: (hints printed to stderr, if any)
  CLI->>MCP: call create-doc / update-doc with args (includes markdown)
  MCP-->>CLI: response/result
  CLI-->>User: print result
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • fangshuyu-768

Poem

🐰 I peeked at markdown, found callouts bare,
I nudged in colors, whispered what to pair.
Hints hop to stderr, gentle and clear,
So docs dress up bright when readers draw near.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 28.57% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title accurately describes the main change: adding a diagnostic warning when callout elements use type= without background-color.
Description check ✅ Passed The description comprehensively covers summary, changes, test plan, and related issues, following the template structure with detailed implementation rationale.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/callout-type-to-color

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.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 14, 2026

🚀 PR Preview Install Guide

🧰 CLI update

npm i -g https://pkg.pr.new/larksuite/cli/@larksuite/cli@b33d5c21079107d6894204b79c5a4689832bbba5

🧩 Skill update

npx skills add larksuite/cli#feat/callout-type-to-color -y -g

Copy link
Copy Markdown

@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: 1

🧹 Nitpick comments (1)
shortcuts/doc/markdown_fix.go (1)

38-40: Broaden fence detection for create-time preprocessing.

prepareMarkdownForCreate now runs on hand-authored markdown, but applyOutsideCodeFences only recognizes bare triple-backtick fences. That can misclassify ~~~, 4+-backtick fences, or blockquote-prefixed fences and lead to missed/incorrect transformations around code blocks. Consider centralizing fence parsing (prefix + marker + length) and reusing it here.

Based on learnings: applyOutsideCodeFences ... only recognize bare triple-backtick fences ... accepted limitation ... because fetch-doc export currently emits only bare triple-backtick fences.

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

In `@shortcuts/doc/markdown_fix.go` around lines 38 - 40, prepareMarkdownForCreate
currently delegates to applyOutsideCodeFences which only recognizes bare
triple-backtick fences; update the code so fence detection is centralized and
supports fence prefix (optional blockquote '>' or spaces), marker char (` or ~),
and variable length (3+). Introduce or reuse a shared fence-parsing helper
(e.g., parseFence or fenceRegex used by applyOutsideCodeFences) and call it from
both applyOutsideCodeFences and prepareMarkdownForCreate (or make
applyOutsideCodeFences accept the new parser) so create-time preprocessing
correctly skips/handles fences like ~~~, 4+ backticks, and blockquote-prefixed
fences while preserving existing behavior for fetch-doc exports.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@shortcuts/doc/markdown_fix.go`:
- Around line 262-265: fixCalloutType currently uses typeRe :=
regexp.MustCompile(`\btype="([^"]*)"`) which only matches double-quoted
attributes and leaves single-quoted callouts (e.g., <callout type='warning'>)
unchanged; update the regex used in fixCalloutType (variable typeRe and its use
with attrs and tag) to accept either single or double quotes (for example use a
pattern that captures quote with backreference or a pattern like
\btype=(?:'|")([^'"]*)(?:'|")) and adjust how you read the capture groups from
typeParts accordingly so single-quoted and double-quoted type attributes are
both handled.

---

Nitpick comments:
In `@shortcuts/doc/markdown_fix.go`:
- Around line 38-40: prepareMarkdownForCreate currently delegates to
applyOutsideCodeFences which only recognizes bare triple-backtick fences; update
the code so fence detection is centralized and supports fence prefix (optional
blockquote '>' or spaces), marker char (` or ~), and variable length (3+).
Introduce or reuse a shared fence-parsing helper (e.g., parseFence or fenceRegex
used by applyOutsideCodeFences) and call it from both applyOutsideCodeFences and
prepareMarkdownForCreate (or make applyOutsideCodeFences accept the new parser)
so create-time preprocessing correctly skips/handles fences like ~~~, 4+
backticks, and blockquote-prefixed fences while preserving existing behavior for
fetch-doc exports.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 99b5687c-bc19-48c5-bb18-d0fd4e78ba9a

📥 Commits

Reviewing files that changed from the base of the PR and between 20761fa and a59a0d0.

📒 Files selected for processing (4)
  • shortcuts/doc/docs_create.go
  • shortcuts/doc/docs_update.go
  • shortcuts/doc/markdown_fix.go
  • shortcuts/doc/markdown_fix_test.go

Comment thread shortcuts/doc/markdown_fix.go Outdated
@SunPeiYang996
Copy link
Copy Markdown
Collaborator

Thanks for the PR and the thorough test coverage!
However, I think this change puts protocol-adaptation logic in the wrong layer. The type → color mapping is essentially compensating for a gap in the create-doc API itself. If we add this to the shortcut, every other client that calls create-doc will need to duplicate the same mapping.
A few specific concerns:

The mapping (e.g. warning → light-yellow) is not defined by any Feishu spec — it's a convention we'd be inventing and then silently applying.
It transforms user input without any visibility, making debugging harder.
It expands the shortcut's responsibility from "invoke MCP" to "fix MCP's input format."

Suggested alternatives:

File a feature request for create-doc to natively support type= on callout blocks.
If we need a short-term workaround, make it an explicit opt-in flag (e.g. --fix-callout-types) with a deprecation plan.
Or, surface a clear warning when type= is used without background-color, telling the user what to write instead.

Happy to discuss further!

Copy link
Copy Markdown

@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: 1

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

Inline comments:
In `@shortcuts/doc/markdown_fix.go`:
- Around line 261-263: The check that skips tags with an explicit background
color is too strict: it only looks for the literal substring "background-color="
using strings.Contains(attrs, "background-color="), so forms like
'background-color = "light-yellow"' or with varied spacing/quotes are missed;
update the detection in the markdown_fix.go logic that currently inspects attrs
(the variable checked and returns tag) to use a whitespace-tolerant match (e.g.,
a regex or normalize attrs by collapsing whitespace) to detect
"background-color" followed by optional spaces and an '='
(background-color\s*=?), and then skip returning the hint when that match is
present. Ensure the change targets the same check that returns tag and continues
to accept other attributes unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d8d41789-3d3c-40cb-8744-954cabb9b237

📥 Commits

Reviewing files that changed from the base of the PR and between a59a0d0 and 011da3d.

📒 Files selected for processing (4)
  • shortcuts/doc/docs_create.go
  • shortcuts/doc/docs_update.go
  • shortcuts/doc/markdown_fix.go
  • shortcuts/doc/markdown_fix_test.go
🚧 Files skipped from review as they are similar to previous changes (3)
  • shortcuts/doc/docs_update.go
  • shortcuts/doc/docs_create.go
  • shortcuts/doc/markdown_fix_test.go

Comment thread shortcuts/doc/markdown_fix.go Outdated
@herbertliu
Copy link
Copy Markdown
Collaborator Author

Thanks for the detailed review and the thoughtful suggestions!

You're right — silently rewriting user Markdown is the wrong approach here. The latest commit (011da3d) replaces fixCalloutType() with WarnCalloutType(), which:

  • Leaves the Markdown unchanged — user input reaches create-doc exactly as written
  • Writes a hint to stderr for each type= callout missing background-color, e.g.:
    hint: callout type="warning" has no background-color; consider: background-color="light-yellow" border-color="yellow"
    

This surfaces the issue visibly without any silent transformation. On the longer term, filing a feature request for create-doc to natively support type= makes sense — happy to do that as a follow-up.

@herbertliu herbertliu force-pushed the feat/callout-type-to-color branch from 011da3d to 24fd1b7 Compare April 16, 2026 09:59
Copy link
Copy Markdown

@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.

♻️ Duplicate comments (1)
shortcuts/doc/markdown_fix.go (1)

261-266: ⚠️ Potential issue | 🟡 Minor

Make attribute matching whitespace-tolerant to avoid false hints/misses.

Line 262 only detects the exact token background-color=, and Line 265 requires type= with no surrounding spaces. Valid forms like background-color = "light-yellow" or type = 'warning' can be misclassified.

🔧 Suggested patch
 var calloutOpenTagRe = regexp.MustCompile(`<callout(\s[^>]*)?>`)
-var calloutTypeAttrRe = regexp.MustCompile(`\btype=(?:"([^"]*)"|'([^']*)')`)
+var calloutTypeAttrRe = regexp.MustCompile(`\btype\s*=\s*(?:"([^"]*)"|'([^']*)')`)
+var calloutBackgroundColorAttrRe = regexp.MustCompile(`\bbackground-color\s*=`)

 func WarnCalloutType(md string, w io.Writer) {
 	calloutOpenTagRe.ReplaceAllStringFunc(md, func(tag string) string {
 		attrs := ""
 		if m := calloutOpenTagRe.FindStringSubmatch(tag); len(m) == 2 {
 			attrs = m[1]
 		}
 		// Skip tags that already carry an explicit background-color.
-		if strings.Contains(attrs, "background-color=") {
+		if calloutBackgroundColorAttrRe.MatchString(attrs) {
 			return tag
 		}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@shortcuts/doc/markdown_fix.go` around lines 261 - 266, The attribute checks
in markdown_fix.go are too strict: replace the exact token checks so they
tolerate optional whitespace around `=` and quotes; specifically, update the
background-color test (currently using strings.Contains(attrs,
"background-color=")) to use a whitespace-tolerant match (e.g., a regex like
`background-color\s*=`) and adjust the calloutTypeAttrRe usage or its pattern so
calloutTypeAttrRe.FindStringSubmatch(attrs) accepts `type` with spaces (e.g.,
`type\s*=\s*["']?(\w+)["']?`), ensuring both background-color and type
attributes are correctly detected regardless of surrounding spaces or quote
style.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@shortcuts/doc/markdown_fix.go`:
- Around line 261-266: The attribute checks in markdown_fix.go are too strict:
replace the exact token checks so they tolerate optional whitespace around `=`
and quotes; specifically, update the background-color test (currently using
strings.Contains(attrs, "background-color=")) to use a whitespace-tolerant match
(e.g., a regex like `background-color\s*=`) and adjust the calloutTypeAttrRe
usage or its pattern so calloutTypeAttrRe.FindStringSubmatch(attrs) accepts
`type` with spaces (e.g., `type\s*=\s*["']?(\w+)["']?`), ensuring both
background-color and type attributes are correctly detected regardless of
surrounding spaces or quote style.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: fe0a4202-ac68-4b52-9bcd-3ecd2721b210

📥 Commits

Reviewing files that changed from the base of the PR and between 011da3d and 24fd1b7.

📒 Files selected for processing (4)
  • shortcuts/doc/docs_create.go
  • shortcuts/doc/docs_update.go
  • shortcuts/doc/markdown_fix.go
  • shortcuts/doc/markdown_fix_test.go
✅ Files skipped from review due to trivial changes (1)
  • shortcuts/doc/markdown_fix_test.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • shortcuts/doc/docs_update.go
  • shortcuts/doc/docs_create.go

Copy link
Copy Markdown

@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.

🧹 Nitpick comments (1)
shortcuts/doc/markdown_fix.go (1)

261-287: Nit: ReplaceAllStringFunc used for side effects only.

The returned string is discarded; calloutOpenTagRe.FindAllStringSubmatchIndex (or iterating FindAllStringSubmatch) would express intent more directly and also skip the redundant second FindStringSubmatch on each matched tag (you already have the capture from the outer find). Purely stylistic — no behavior change needed.

♻️ Optional refactor
-func WarnCalloutType(md string, w io.Writer) {
-	calloutOpenTagRe.ReplaceAllStringFunc(md, func(tag string) string {
-		attrs := ""
-		if m := calloutOpenTagRe.FindStringSubmatch(tag); len(m) == 2 {
-			attrs = m[1]
-		}
-		// Skip tags that already carry an explicit background-color.
-		if calloutBackgroundColorAttrRe.MatchString(attrs) {
-			return tag
-		}
-		parts := calloutTypeAttrRe.FindStringSubmatch(attrs)
-		if len(parts) < 2 {
-			return tag // no type= attribute
-		}
-		// parts[1] is the double-quoted capture, parts[2] is single-quoted.
-		typeName := parts[1]
-		if typeName == "" {
-			typeName = parts[2]
-		}
-		colors, ok := calloutTypeColors[typeName]
-		if !ok {
-			return tag // unknown type — no hint to give
-		}
-		fmt.Fprintf(w,
-			"hint: callout type=%q has no background-color; consider: background-color=%q border-color=%q\n",
-			typeName, colors[0], colors[1])
-		return tag
-	})
-}
+func WarnCalloutType(md string, w io.Writer) {
+	for _, m := range calloutOpenTagRe.FindAllStringSubmatch(md, -1) {
+		attrs := m[1]
+		if calloutBackgroundColorAttrRe.MatchString(attrs) {
+			continue
+		}
+		parts := calloutTypeAttrRe.FindStringSubmatch(attrs)
+		if len(parts) < 3 {
+			continue
+		}
+		typeName := parts[1]
+		if typeName == "" {
+			typeName = parts[2]
+		}
+		colors, ok := calloutTypeColors[typeName]
+		if !ok {
+			continue
+		}
+		fmt.Fprintf(w,
+			"hint: callout type=%q has no background-color; consider: background-color=%q border-color=%q\n",
+			typeName, colors[0], colors[1])
+	}
+}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@shortcuts/doc/markdown_fix.go` around lines 261 - 287, Replace the
ReplaceAllStringFunc usage (calloutOpenTagRe.ReplaceAllStringFunc) which
discards its returned string with a direct iteration over matches using
calloutOpenTagRe.FindAllStringSubmatch (or FindAllStringSubmatchIndex) so you
can use the captured attrs directly (avoid calling
calloutOpenTagRe.FindStringSubmatch again); for each match, skip when
calloutBackgroundColorAttrRe matches, extract the type via calloutTypeAttrRe
from the already-captured groups, look up calloutTypeColors[typeName], and write
the hint to w when appropriate—this makes the intent explicit and removes the
redundant regex call.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@shortcuts/doc/markdown_fix.go`:
- Around line 261-287: Replace the ReplaceAllStringFunc usage
(calloutOpenTagRe.ReplaceAllStringFunc) which discards its returned string with
a direct iteration over matches using calloutOpenTagRe.FindAllStringSubmatch (or
FindAllStringSubmatchIndex) so you can use the captured attrs directly (avoid
calling calloutOpenTagRe.FindStringSubmatch again); for each match, skip when
calloutBackgroundColorAttrRe matches, extract the type via calloutTypeAttrRe
from the already-captured groups, look up calloutTypeColors[typeName], and write
the hint to w when appropriate—this makes the intent explicit and removes the
redundant regex call.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 410deed8-c468-499b-b13e-aee867ffa0a3

📥 Commits

Reviewing files that changed from the base of the PR and between 24fd1b7 and b4e9d47.

📒 Files selected for processing (2)
  • shortcuts/doc/markdown_fix.go
  • shortcuts/doc/markdown_fix_test.go
✅ Files skipped from review due to trivial changes (1)
  • shortcuts/doc/markdown_fix_test.go

@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 20, 2026

Codecov Report

❌ Patch coverage is 94.28571% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 64.51%. Comparing base (2e4cfb4) to head (b33d5c2).
⚠️ Report is 32 commits behind head on main.

Files with missing lines Patch % Lines
shortcuts/doc/docs_update.go 0.00% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #467      +/-   ##
==========================================
+ Coverage   63.20%   64.51%   +1.31%     
==========================================
  Files         491      516      +25     
  Lines       42237    45765    +3528     
==========================================
+ Hits        26694    29527    +2833     
- Misses      13211    13652     +441     
- Partials     2332     2586     +254     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Copy Markdown
Collaborator

@fangshuyu-768 fangshuyu-768 left a comment

Choose a reason for hiding this comment

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

Direction looks right — the switch from rewriting markdown to hint-only is a healthier boundary. A few notes on the current implementation, plus a PR-description update request.

Comment thread shortcuts/doc/markdown_fix.go Outdated
Comment thread shortcuts/doc/markdown_fix.go
Comment thread shortcuts/doc/markdown_fix.go Outdated
Comment thread shortcuts/doc/markdown_fix.go Outdated
@herbertliu herbertliu force-pushed the feat/callout-type-to-color branch from 7d4b556 to 2d8285e Compare April 23, 2026 02:21
…order-color

When users write <callout type="warning" emoji="📝"> without an explicit
background-color, the Feishu doc renders the block with no color. This
commit adds fixCalloutType() which maps the semantic type= attribute to
the corresponding background-color/border-color pair accepted by create-doc.

- warning → light-yellow/yellow
- info/note → light-blue/blue
- tip/success/check → light-green/green
- error/danger → light-red/red
- caution → light-orange/orange
- important → light-purple/purple

Explicit background-color or border-color attributes are always preserved.
The fix is applied via prepareMarkdownForCreate() in both +create and
+update paths, and also inside fixExportedMarkdown() for round-trip fidelity.
…output

Per reviewer feedback (SunPeiYang996), silently rewriting user Markdown is
the wrong layer for this adaptation. The type→color mapping is not part of
the Feishu spec, and covert transforms make debugging harder.

Replace fixCalloutType() (which rewrote the Markdown) with WarnCalloutType()
which leaves the Markdown unchanged and instead writes a hint line to stderr
for each callout tag that has type= but no background-color, telling the user
the recommended explicit attributes to add:

  hint: callout type="warning" has no background-color; consider: background-color="light-yellow" border-color="yellow"

Also fixes CodeRabbit feedback: the type= regex now accepts both single-quoted
and double-quoted attribute values (type='warning' and type="warning").
CodeRabbit flagged that the previous strings.Contains(attrs,
"background-color=") check missed forms like 'background-color =
"light-red"' with whitespace around the equals sign. Replace with a
regex that tolerates optional whitespace, and add a regression test.
@herbertliu herbertliu force-pushed the feat/callout-type-to-color branch from 2d8285e to 1950398 Compare April 28, 2026 09:20
PR #467's review thread had three substantive comments
(`fangshuyu-768`, 2026-04-21) that the prior reply messages claimed
were fixed in commit 7d4b556 — but that commit no longer exists on the
branch (lost in a rebase / squash), and the head still ships the
original buggy code. This commit makes the fixes real.

Three behavior fixes in shortcuts/doc/markdown_fix.go:

1. (#5) Tighten the type= and background-color= regex anchors. \b sits
   at any word/non-word boundary, and `-` is a non-word char, so
   `\btype=` also matched the suffix of `data-type=` — a tag like
   `<callout data-type="warning">` would emit a bogus light-yellow
   hint. Switched both regexes to `(?:^|\s)…` so a real attribute
   separator is required. The same anchor on background-color closes
   the symmetric case where a `data-background-color=` attribute
   would silently suppress the real hint.

2. (#4) WarnCalloutType is now a fence-aware line walker. Previously
   the regex ran over the entire markdown body, so a callout sample
   inside a documentation code fence (```markdown … ```) would
   generate a phantom stderr hint every time the docs mentioned the
   feature. The walker tracks fence state via the existing
   codeFenceOpenMarker / isCodeFenceClose helpers from
   docs_update_check.go, which handle both backtick and tilde fences
   per CommonMark §4.5.

3. (#3) Drop the ReplaceAllStringFunc-as-iterator pattern. The
   previous code routed callout iteration through a rewrite primitive
   whose rebuilt-string return value was discarded, then ran the same
   regex a second time inside the callback to recover the capture
   groups. New scanCalloutTagsForWarning helper uses
   FindAllStringSubmatch — one pass, no thrown-away allocation,
   intent matches the surface (read-only scan, not a mutator).

Tests: 5 new TestWarnCalloutType subtests pin each contract:

- data-type attribute does not trigger hint (#5)
- data-background-color does not suppress hint (#5, symmetric)
- callout inside backtick fence emits no hint (#4)
- callout inside tilde fence emits no hint (#4)
- callout after fence close still emits hint (#4, fence-state reset)

All 14 TestWarnCalloutType cases pass; go vet / golangci-lint
--new-from-rev=origin/main both clean.
@fangshuyu-768 fangshuyu-768 changed the title feat(doc): expand callout type= shorthand into background-color and border-color feat(doc): warn when callout uses type= without background-color Apr 30, 2026
@fangshuyu-768 fangshuyu-768 merged commit cfd89e0 into main Apr 30, 2026
21 checks passed
@fangshuyu-768 fangshuyu-768 deleted the feat/callout-type-to-color branch April 30, 2026 09:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

domain/ccm PR touches the ccm domain size/M Single-domain feat or fix with limited business impact

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants