feat(docx): add hi-fidelity XML injections for tables, styles, lists, and sections; extend tools and tests

- Add feature flags: hi-fidelity-tables, hi-fidelity-styles, hi-fidelity-lists, hi-fidelity-sections
- Tables: inject true w:gridSpan/w:vMerge and w:tblGrid widths via post-build XML when enabled
- Styles: ensure TableHeader style in styles.xml; tag first row when headers present
- Lists: robust numbering.xml for ordered/unordered with multi-level definitions
- Sections: write tail w:sectPr with page size/orientation/margins
- Tools: expose new operations (sections, list items, images, hyperlinks, props, redaction, storage)
- Converters: add preference-aware methods for hi-fidelity export paths; HTML export tool
- Tests: add golden XML assertions gated by feature flags; keep default build green

This enables high-fidelity DOCX output while keeping pure-Rust paths by default.
This commit is contained in:
Andy
2025-08-12 23:25:29 +08:00
parent c30f55d16d
commit 90305551cc
14 changed files with 1983 additions and 277 deletions
+42
View File
@@ -0,0 +1,42 @@
use serde::{Serialize, Deserialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum ToolOutcome {
Ok { message: Option<String> },
Created { document_id: String, message: Option<String> },
Text { text: String },
Metadata { metadata: serde_json::Value },
Documents { documents: serde_json::Value },
Images { images: Vec<String>, message: Option<String> },
Security { security: serde_json::Value },
Storage { storage: serde_json::Value },
Statistics { statistics: serde_json::Value },
Structure { structure: serde_json::Value },
Error { code: ErrorCode, error: String, hint: Option<String> },
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum ErrorCode {
DocNotFound,
ValidationError,
SecurityDenied,
LimitExceeded,
UnknownTool,
InternalError,
}
impl ToolOutcome {
pub fn success(&self) -> bool {
!matches!(self, ToolOutcome::Error { .. })
}
pub fn into_json(self) -> serde_json::Value {
serde_json::to_value(self).unwrap_or_else(|e| serde_json::json!({
"type": "error",
"code": ErrorCode::InternalError,
"error": format!("serialization failed: {}", e),
}))
}
}