From d667544d0593c449d9380c338eeacd26603f2b86 Mon Sep 17 00:00:00 2001 From: AI Engineer Date: Sun, 21 Jun 2026 10:17:40 +0800 Subject: [PATCH] =?UTF-8?q?feat(document):=20=E5=85=B7=E5=90=8D=E5=8C=96?= =?UTF-8?q?=20JS=20=E5=AF=BC=E5=87=BA=E5=B9=B6=E5=8A=A8=E6=80=81=E5=8C=85?= =?UTF-8?q?=E8=A3=B9=E9=94=99=E8=AF=AF=EF=BC=88by=20AI=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 4 +++ TEST.md | 27 +++++++++++++++ go.mod | 12 +++---- js_export.go | 93 ++++++++++++++++++++++++++++++++-------------------- 4 files changed, 95 insertions(+), 41 deletions(-) create mode 100644 TEST.md diff --git a/CHANGELOG.md b/CHANGELOG.md index de6b482..0256b18 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # CHANGELOG +## v1.5.3 (2026-06-21) +- **JS 对齐**: 重构 JS 导出为具名函数,并引入 `jsmod.MakeError` 动态包装错误以获取调用栈。 +- **依赖更新**: 升级依赖 `jsmod` 至 `v1.5.3`,`cast` 至 `v1.5.3`,`rand` 至 `v1.5.3`,`encoding` 至 `v1.5.4`,`safe` 至 `v1.5.2`,`file` 至 `v1.5.5`。 + ## v1.5.2 (2026-06-11) - **版本对齐**: 基础设施全局对齐 v1.5.2。 diff --git a/TEST.md b/TEST.md new file mode 100644 index 0000000..5774936 --- /dev/null +++ b/TEST.md @@ -0,0 +1,27 @@ +# Test Report: @go/document + +## 📋 测试概览 +- **测试时间**: 2026-06-21 +- **测试环境**: darwin/amd64 +- **Go 版本**: 1.25.0 + +## ✅ 功能测试 (Functional Tests) +| 场景 | 状态 | 描述 | +| :--- | :--- | :--- | +| `TestExcel_Basic` | PASS | Excel 基础单元格及公式读写测试。 | +| `TestExcel_Data` | PASS | Excel 对象数组及映射读写测试。 | +| `TestUnifiedAPI` | PASS | 统一的 Document 接口 Open/Create/Save 行为测试。 | +| `TestIDGeneration` | PASS | RAG 场景 ID 生成器及映射验证。 | +| `TestGraph_Basic` | PASS | Graph 关系型文档节点及关系建模测试。 | +| `TestGraph_Unified` | PASS | Graph 到 Markdown (Mermaid) 链路集成测试。 | +| `TestCSV` | PASS | CSV 文档对象及表格转换测试。 | +| `TestMarkdown` | PASS | Markdown 格式解析与重构测试。 | + +## 🛡️ 鲁棒性防御 (Robustness) +- **可选参数提示**:`Open` 和 `Save` 方法接受指针作为可选参数,结合最新的 `go/js` 引擎智能过滤空参数。 +- **JS 错误调用栈**:JS 桥接层改用具名导出并使用 `jsmod.MakeError` 包裹错误,确保 JS 抛出异常时携带准确的 Go 运行时堆栈。 + +## ⚡ 性能基准 (Benchmarks) +| 函数 | 平均耗时 | 性能分析 | +| :--- | :--- | :--- | +| `Excel_SetData` | **1874250 ns/op** | Excel 大量数据处理性能指标。 | diff --git a/go.mod b/go.mod index 59f0f7b..2391d1b 100644 --- a/go.mod +++ b/go.mod @@ -3,18 +3,18 @@ module apigo.cc/go/document go 1.25.0 require ( - apigo.cc/go/cast v1.5.2 - apigo.cc/go/file v1.5.4 - apigo.cc/go/jsmod v1.5.2 + apigo.cc/go/cast v1.5.3 + apigo.cc/go/file v1.5.5 + apigo.cc/go/jsmod v1.5.3 github.com/dslipak/pdf v0.0.2 github.com/xuri/excelize/v2 v2.10.1 github.com/young2j/oxmltotext v1.0.3 ) require ( - apigo.cc/go/encoding v1.5.3 - apigo.cc/go/rand v1.5.2 - apigo.cc/go/safe v1.5.1 + apigo.cc/go/encoding v1.5.4 + apigo.cc/go/rand v1.5.3 + apigo.cc/go/safe v1.5.2 github.com/andybalholm/brotli v1.0.5 // indirect github.com/dgrr/quickxml v0.0.0-20201022091424-4977de546d6c // indirect github.com/klauspost/compress v1.17.0 // indirect diff --git a/js_export.go b/js_export.go index f78151c..da9e773 100644 --- a/js_export.go +++ b/js_export.go @@ -9,38 +9,46 @@ import ( func init() { jsmod.Register("document", map[string]any{ - "Open": func(ctx context.Context, filename string, password *string) (*jsDocument, error) { - p, err := file.VerifyPathForSafeMode(ctx, filename) - if err != nil { - return nil, err - } - var doc Document - if password != nil { - doc, err = Open(p, *password) - } else { - doc, err = Open(p) - } - if err != nil { - return nil, err - } - return &jsDocument{ctx: ctx, d: doc}, nil - }, - "Create": func(ctx context.Context, ext string) (*jsDocument, error) { - doc, err := Create(ext) - if err != nil { - return nil, err - } - return &jsDocument{ctx: ctx, d: doc}, nil - }, - "NewExcel": func(ctx context.Context) *jsDocument { - return &jsDocument{ctx: ctx, d: NewExcel()} - }, - "NewGraph": func(ctx context.Context) *jsDocument { - return &jsDocument{ctx: ctx, d: NewGraph()} - }, + "Open": jsOpen, + "Create": jsCreate, + "NewExcel": jsNewExcel, + "NewGraph": jsNewGraph, }) } +func jsOpen(ctx context.Context, filename string, password *string) (*jsDocument, error) { + p, err := file.VerifyPathForSafeMode(ctx, filename) + if err != nil { + return nil, jsmod.MakeError(err) + } + var doc Document + if password != nil { + doc, err = Open(p, *password) + } else { + doc, err = Open(p) + } + if err != nil { + return nil, jsmod.MakeError(err) + } + return &jsDocument{ctx: ctx, d: doc}, nil +} + +func jsCreate(ctx context.Context, ext string) (*jsDocument, error) { + doc, err := Create(ext) + if err != nil { + return nil, jsmod.MakeError(err) + } + return &jsDocument{ctx: ctx, d: doc}, nil +} + +func jsNewExcel(ctx context.Context) *jsDocument { + return &jsDocument{ctx: ctx, d: NewExcel()} +} + +func jsNewGraph(ctx context.Context) *jsDocument { + return &jsDocument{ctx: ctx, d: NewGraph()} +} + type jsDocument struct { ctx context.Context d Document @@ -54,38 +62,53 @@ func (j *jsDocument) Save(filename *string) error { if filename != nil && *filename != "" { p, err := file.VerifyPathForSafeMode(j.ctx, *filename) if err != nil { - return err + return jsmod.MakeError(err) } targetPath = p } - return j.d.Save(targetPath) + if err := j.d.Save(targetPath); err != nil { + return jsmod.MakeError(err) + } + return nil } // Excel 增强方法 (如果底层是 Excel) func (j *jsDocument) Get(sheetName string, start, end string) ([][]any, error) { if x, ok := j.d.(*Excel); ok { - return x.Get(sheetName, start, end) + res, err := x.Get(sheetName, start, end) + if err != nil { + return nil, jsmod.MakeError(err) + } + return res, nil } return nil, nil } func (j *jsDocument) GetData(sheetName string, start, end string) ([]map[string]any, error) { if x, ok := j.d.(*Excel); ok { - return x.GetData(sheetName, start, end) + res, err := x.GetData(sheetName, start, end) + if err != nil { + return nil, jsmod.MakeError(err) + } + return res, nil } return nil, nil } func (j *jsDocument) Set(sheetName string, table [][]any, start, end string) error { if x, ok := j.d.(*Excel); ok { - return x.Set(sheetName, table, start, end) + if err := x.Set(sheetName, table, start, end); err != nil { + return jsmod.MakeError(err) + } } return nil } func (j *jsDocument) SetData(sheetName string, data []map[string]any, start, end string) error { if x, ok := j.d.(*Excel); ok { - return x.SetData(sheetName, data, start, end) + if err := x.SetData(sheetName, data, start, end); err != nil { + return jsmod.MakeError(err) + } } return nil }