mirror of
https://github.com/larksuite/cli.git
synced 2026-07-06 16:18:05 +08:00
Adds an `--api-version v2` path to the docs shortcuts, backed by the
`docs_ai/v1/documents` OpenAPI. DocxXML is the default document format
and Markdown is available as an alternative. Content input is unified
across the three shortcuts via `--content` + `--doc-format`. The v1
(MCP) path is preserved for backward compatibility and now prints a
deprecation notice on use.
Shortcuts:
- `docs +create --api-version v2`: create a document from XML or
Markdown, with optional `--parent-token` or `--parent-position`.
Bot identity continues to auto-grant the current CLI user
full_access on the new document.
- `docs +fetch --api-version v2`: adds `--detail simple|with-ids|full`
for export granularity and `--scope full|outline|range|keyword|section`
for partial reads, along with `--context-before` / `--context-after`,
`--max-depth`, and `--revision-id`.
- `docs +update --api-version v2`: introduces structured operations
via `--command`: `str_replace`, `block_delete`, `block_insert_after`,
`block_copy_insert_after`, `block_replace`, `block_move_after`,
`overwrite`, `append`.
Framework support in `shortcuts/common`:
- `OutRaw` / `OutFormatRaw` emit the JSON envelope with HTML escaping
disabled so XML/HTML document bodies are preserved verbatim.
- New `Shortcut.PostMount` hook runs after a cobra.Command is fully
configured; used here to install a version-aware help function
that hides flags belonging to the inactive `--api-version`.
Also refreshes the lark-doc skill pack (SKILL.md, create/fetch/update
references, new lark-doc-xml and lark-doc-md references, style and
workflow guides), README examples, and downstream skill call sites
(lark-drive, lark-vc, lark-whiteboard, lark-workflow-meeting-summary,
lark-event).
Change-Id: Ide2d86b190a4e21095ae29096e7fb00031d80489
65 lines
1.9 KiB
Go
65 lines
1.9 KiB
Go
// Copyright (c) 2026 Lark Technologies Pte. Ltd.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package output
|
|
|
|
import (
|
|
"bytes"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestJqFilterRaw_PreservesXMLInComplexValue(t *testing.T) {
|
|
data := map[string]interface{}{
|
|
"data": map[string]interface{}{
|
|
"document": map[string]interface{}{
|
|
"title": "<title>hello & welcome</title>",
|
|
"content": "<p>a < b & c > d</p>",
|
|
},
|
|
},
|
|
}
|
|
|
|
var raw bytes.Buffer
|
|
if err := JqFilterRaw(&raw, data, ".data.document"); err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
// Raw path must keep <, >, & as literal characters, not Go json-encoder's
|
|
// default < / > / & unicode escapes.
|
|
for _, unicodeEsc := range []string{"\\u003c", "\\u003e", "\\u0026"} {
|
|
if strings.Contains(raw.String(), unicodeEsc) {
|
|
t.Errorf("JqFilterRaw unexpectedly HTML-escaped %s: %s", unicodeEsc, raw.String())
|
|
}
|
|
}
|
|
if !strings.Contains(raw.String(), "<title>") {
|
|
t.Errorf("JqFilterRaw dropped raw <title>: %s", raw.String())
|
|
}
|
|
|
|
var escaped bytes.Buffer
|
|
if err := JqFilter(&escaped, data, ".data.document"); err != nil {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
// JqFilter keeps Go's default HTML escaping for back-compat.
|
|
if !strings.Contains(escaped.String(), "\\u003c") {
|
|
t.Errorf("JqFilter should HTML-escape < for back-compat: %s", escaped.String())
|
|
}
|
|
}
|
|
|
|
func TestJqFilterRaw_ScalarMatchesJqFilter(t *testing.T) {
|
|
data := map[string]interface{}{"content": "<title>hello</title>"}
|
|
|
|
var raw, plain bytes.Buffer
|
|
if err := JqFilterRaw(&raw, data, ".content"); err != nil {
|
|
t.Fatalf("raw: %v", err)
|
|
}
|
|
if err := JqFilter(&plain, data, ".content"); err != nil {
|
|
t.Fatalf("plain: %v", err)
|
|
}
|
|
// Scalar string path is raw in both (matches jq -r), so output is identical.
|
|
if raw.String() != plain.String() {
|
|
t.Errorf("scalar output diverged: raw=%q plain=%q", raw.String(), plain.String())
|
|
}
|
|
if !strings.Contains(raw.String(), "<title>") {
|
|
t.Errorf("scalar output dropped <title>: %q", raw.String())
|
|
}
|
|
}
|