Skip to content

feat(doc): expand callout type= shorthand into background-color and border-color#467

Open
herbertliu wants to merge 1 commit intomainfrom
feat/callout-type-to-color
Open

feat(doc): expand callout type= shorthand into background-color and border-color#467
herbertliu wants to merge 1 commit intomainfrom
feat/callout-type-to-color

Conversation

@herbertliu
Copy link
Copy Markdown
Collaborator

@herbertliu herbertliu commented Apr 14, 2026

Summary

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

Changes

  • shortcuts/doc/markdown_fix.go: Add calloutTypeColors mapping table, fixCalloutType() function, and prepareMarkdownForCreate() helper; integrate fixCalloutType into fixExportedMarkdown() for round-trip fidelity
  • shortcuts/doc/docs_create.go: Apply prepareMarkdownForCreate() to markdown before sending to MCP
  • shortcuts/doc/docs_update.go: Same as above for the update path (both DryRun and Execute)
  • shortcuts/doc/markdown_fix_test.go: Add TestFixCalloutType with 11 table-driven cases

type → color mapping

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

Explicit background-color or border-color attributes on the tag are always preserved (never overwritten).

Test Plan

  • Unit tests pass (go test ./shortcuts/doc/...) — coverage 64.5%
  • go vet ./... clean
  • golangci-lint run --new-from-rev=origin/main — 0 issues
  • gofmt clean

Related Issues

  • Fixes callout background color missing when using type= semantic shorthand

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Callout elements in markdown now automatically receive default background and border colors based on their type when creating or updating documents.

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

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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

📝 Walkthrough

Walkthrough

The PR adds automatic color injection for callout tags in Markdown documentation. When creating or updating docs, markdown is now preprocessed through a new prepareMarkdownForCreate() function that applies fixCalloutType() to callout tags outside code blocks, automatically injecting default background and border colors based on the callout's type attribute (warning, info, tip, error, important, caution).

Changes

Cohort / File(s) Summary
Markdown preprocessing logic
shortcuts/doc/markdown_fix.go
Added prepareMarkdownForCreate() public helper, fixCalloutType() function that injects background/border colors to callout tags based on type attribute, and calloutTypeColors mapping storing default color pairs for known types (warning, info, tip, error, important, caution). Extended fixExportedMarkdown pipeline to include callout type fixing.
Create and update integration
shortcuts/doc/docs_create.go, shortcuts/doc/docs_update.go
Modified buildDocsCreateArgs() and update handlers to preprocess markdown via prepareMarkdownForCreate() before passing to MCP tool instead of using raw markdown directly.
Test coverage
shortcuts/doc/markdown_fix_test.go
Added comprehensive TestFixCalloutType unit test validating automatic color injection for known callout types, preservation of explicitly-provided colors, and no-op behavior for unknown types or missing type attributes.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested labels

size/L, domain/ccm

Suggested reviewers

  • fangshuyu-768

Poem

🐰 Colorful callouts hop into place,
With backgrounds and borders with grace,
Type-mapped and true, both warning and wise,
The markdown now shines before docs' eyes!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and specifically describes the main change: expanding semantic callout type= attributes into explicit background-color and border-color attributes.
Description check ✅ Passed The description comprehensively covers all required template sections: clear summary explaining the motivation, detailed changes across four files, complete test plan with specific commands run, and related issue context.

✏️ 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

🚀 PR Preview Install Guide

🧰 CLI update

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

🧩 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 on lines +262 to +265
typeRe := regexp.MustCompile(`\btype="([^"]*)"`)
typeParts := typeRe.FindStringSubmatch(attrs)
if len(typeParts) != 2 {
return tag // no type= attribute
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

fixCalloutType misses single-quoted type attributes.

Line 262 only matches type="...". Tags like <callout type='warning'> are left unchanged, so shorthand expansion silently fails.

[sraise_minor_fix_note]

🔧 Proposed fix
 var calloutTypeRe = regexp.MustCompile(`<callout(\s[^>]*)?>`)
+var calloutTypeAttrRe = regexp.MustCompile(`\btype=(?:"([^"]*)"|'([^']*)')`)

 func fixCalloutType(md string) string {
 	return calloutTypeRe.ReplaceAllStringFunc(md, func(tag string) string {
 		attrs := ""
 		if m := calloutTypeRe.FindStringSubmatch(tag); len(m) == 2 {
 			attrs = m[1]
 		}
-		// Extract type value.
-		typeRe := regexp.MustCompile(`\btype="([^"]*)"`)
-		typeParts := typeRe.FindStringSubmatch(attrs)
-		if len(typeParts) != 2 {
+		typeParts := calloutTypeAttrRe.FindStringSubmatch(attrs)
+		if len(typeParts) != 3 {
 			return tag // no type= attribute
 		}
-		typeName := typeParts[1]
+		typeName := typeParts[1]
+		if typeName == "" {
+			typeName = typeParts[2]
+		}
 		colors, ok := calloutTypeColors[typeName]
 		if !ok {
 			return tag // unknown type — leave as-is
 		}
📝 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
typeRe := regexp.MustCompile(`\btype="([^"]*)"`)
typeParts := typeRe.FindStringSubmatch(attrs)
if len(typeParts) != 2 {
return tag // no type= attribute
var calloutTypeRe = regexp.MustCompile(`<callout(\s[^>]*)?>`)
var calloutTypeAttrRe = regexp.MustCompile(`\btype=(?:"([^"]*)"|'([^']*)')`)
func fixCalloutType(md string) string {
return calloutTypeRe.ReplaceAllStringFunc(md, func(tag string) string {
attrs := ""
if m := calloutTypeRe.FindStringSubmatch(tag); len(m) == 2 {
attrs = m[1]
}
typeParts := calloutTypeAttrRe.FindStringSubmatch(attrs)
if len(typeParts) != 3 {
return tag // no type= attribute
}
typeName := typeParts[1]
if typeName == "" {
typeName = typeParts[2]
}
colors, ok := calloutTypeColors[typeName]
if !ok {
return tag // unknown type — leave as-is
}
🤖 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 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.

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

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.

2 participants