Skip to content

feat: CLI JSON-RPC wrapper + Node.js integration (Issue #19)#24

Open
mmonterroca wants to merge 13 commits intomasterfrom
dev
Open

feat: CLI JSON-RPC wrapper + Node.js integration (Issue #19)#24
mmonterroca wants to merge 13 commits intomasterfrom
dev

Conversation

@mmonterroca
Copy link
Copy Markdown
Owner

@mmonterroca mmonterroca commented Mar 18, 2026

Summary

CLI JSON-RPC wrapper + Node.js integration for docxgo, implementing all sections of Issue #19.

Enables document creation and manipulation from Node.js (and any language) via a JSON-RPC binary that communicates over stdin/stdout — zero config, zero ports, zero auth.

What's Included

CLI Binary (cmd/docxgo/)

  • 22 RPC methods over stdin/stdout (NDJSON protocol)
  • Two modes: exec (single request) and rpc (persistent session)
  • Methods: system.{ping,version,capabilities,batch}, document.{create,open,save,validate,inspect,setMetadata,setBackgroundColor,addContent,addPageBreak,applyPatch,close}, paragraph.{add,list}, table.{add,list}, section.add, template.{inspect,render}
  • 73 Go tests

Node.js Wrapper (npm/)

  • @mmonterroca/docxgo — TypeScript CJS + ESM package
  • Three API levels: DocxgoExec (one-shot), DocxgoRPC (low-level persistent), DocumentBuilder (high-level fluent)
  • Full type safety with TypeScript declarations
  • 30 Node.js tests

CI/CD (.github/workflows/)

  • release.yml: Multi-platform Go binary builds (darwin/linux/windows × arm64/x64) + GitHub Release
  • npm-publish.yml: Platform-specific npm packages with OIDC provenance
  • ci.yml: Updated with npm-test job

Documentation

  • docs/CLI_GUIDE.md: Full reference for all 22 methods with examples
  • npm/README.md: Installation, quick start, API reference

Reader Fix

  • Metadata round-trip: Reader now parses docProps/core.xml during document open, so metadata (title, creator, subject, etc.) survives save → reopen cycles

Commits (9)

Commit Description
5d2bfc9 feat(cli): add mutation RPC methods for document manipulation
ae75fb4 feat(npm): add Node.js wrapper for docxgo CLI
84cb54e feat(cli): add system., template., document.applyPatch, system.batch methods
91de4cd docs: CLI_GUIDE.md + npm README updates
79f33a4 ci: release + npm publish workflows
60225ca ci(npm): OIDC provenance support
778d760 fix: resolve 16 golangci-lint errors
55c28d9 fix: address PR #24 code review feedback
eab4589 feat(reader): parse metadata from docProps/core.xml on document open

Review Feedback Addressed

All 9 code review comments resolved:

  • Removed false atomicity claim from document.applyPatch docs
  • Fixed template.inspect to honor custom delimiters
  • Fixed setMetadata in applyPatch to use anonymous struct (no redundant DocumentID)
  • Fixed rpc.ts stdin.write error handling (try/catch + pending cleanup)
  • Fixed npm-publish.yml OS mapping (windowswin32)
  • Fixed main.go json.MarshalIndent error handling
  • Fixed npm test script to run source tests via tsx

Test Results

  • Go: 73/73 tests pass (with -race)
  • Node.js: 30/30 tests pass
  • CLI integration: 32/32 RPC method checks pass
  • TypeScript: tsc --noEmit clean
  • CI: All checks green ✅

Closes #19

Add 7 new JSON-RPC methods to complete the CLI layer:
- document.addContent: append content array to existing documents
- document.addPageBreak: add page break to existing documents
- paragraph.add: add single paragraph with full formatting
- paragraph.list: list all paragraphs with text/style/index
- table.add: add table with rows/cells/borders
- table.list: list all tables with dimensions
- section.add: add section with page layout and headers/footers

Includes 17 new tests (49 total) and updated CLI_GUIDE.md.
Closes section A of #19.
- TypeScript package @mmonterroca/docxgo with CJS + ESM support
- DocxgoExec: synchronous one-shot client (execFileSync)
- DocxgoRPC: async persistent client (child_process.spawn)
- DocumentBuilder: fluent API for creating and modifying documents
- Binary resolver with platform-specific package support
- Complete type definitions for all 15 RPC methods
- 17 tests across 4 suites (resolveBinary, DocxgoExec, DocxgoRPC, DocumentBuilder)
- ESM build script (scripts/build-esm.js)
- Comprehensive README with API reference and examples

Implements Section B of issue #19
…h methods

- system.ping, system.version, system.capabilities for health/feature discovery
- system.batch for multi-request single roundtrip execution
- template.inspect to discover placeholders with location details
- template.render to merge template data with strict mode + warnings
- document.applyPatch for atomic multi-operation patching (6 op types)
- version --json flag with capabilities map
- Enriched RPCError with data field (category, retryable, index)
- Node.js wrapper: new types, builder methods, DocxgoError.data
- Go tests: 73 pass (+24 new)
- Node.js tests: 30 pass (+13 new)
… npm README

- CLI_GUIDE.md: added 7 new methods to TOC, enriched error format docs,
  full reference for system.ping/version/capabilities/batch,
  template.inspect/render, document.applyPatch, TEMPLATE_ERROR code
- npm/README.md: added template workflow example, patch operations example,
  system/template/patch builder method tables, enriched DocxgoError.data
  examples, updated RPC methods table (15 → 22 methods)
- release.yml: builds Go binaries for 5 platforms (darwin-arm64/x64,
  linux-x64/arm64, win32-x64) with CGO_ENABLED=0, creates GH Release
  with archives + checksums
- npm-publish.yml: triggered on GH Release, publishes platform-specific
  @mmonterroca/docxgo-{platform} packages then main package with
  matching optionalDependencies versions
- ci.yml: fixed branch names (main→master), added npm-test job that
  builds Go binary and runs Node.js tests
- npm/platforms/: scaffold for platform binary packages
- Added id-token: write permission for OIDC
- Added --provenance flag to npm publish commands
- Added max-parallel: 1 to platform matrix (npm rate limits)
@gemini-code-assist
Copy link
Copy Markdown

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly expands the utility of the docxgo library by introducing a robust command-line interface (CLI) with JSON-RPC capabilities and a dedicated Node.js wrapper. This allows developers to programmatically create, manipulate, and manage Word documents from both Go and Node.js environments, enabling powerful automation and integration scenarios. The changes include new RPC methods for document content manipulation, templating, and batch processing, alongside comprehensive testing and CI/CD pipelines for multi-platform binary distribution.

Highlights

  • CLI JSON-RPC Wrapper (Go): Introduced a comprehensive CLI JSON-RPC wrapper for the docxgo library, supporting both one-shot (docxgo exec) and persistent (docxgo rpc) modes. This includes 22 new RPC methods across 6 namespaces (system, document, paragraph, table, section, template) and enriched error responses with detailed data.
  • Node.js Integration: Developed a new Node.js wrapper (@mmonterroca/docxgo) with three client modes: DocxgoExec for synchronous one-shot calls, DocxgoRPC for asynchronous persistent connections, and DocumentBuilder for a fluent API. It supports template inspection/rendering, patch operations, and batch requests.
  • Cross-Platform Binary Resolution: Implemented automatic cross-platform binary resolution for the Node.js wrapper, utilizing optional dependencies for macOS, Linux, and Windows (x64 & arm64) to simplify installation.
  • CI/CD Enhancements: Added new GitHub Actions workflows (release.yml, npm-publish.yml) for building Go binaries across 5 platforms, creating GitHub Releases, and publishing platform-specific and main npm packages with OIDC provenance. The existing ci.yml was also updated.
  • Extensive Documentation & Testing: Provided detailed documentation in docs/CLI_GUIDE.md for all 22 RPC methods and a comprehensive npm/README.md for the Node.js wrapper. Added 73 Go tests and 30 Node.js tests to ensure functionality and stability.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Ignored Files
  • Ignored by pattern: .github/workflows/** (3)
    • .github/workflows/ci.yml
    • .github/workflows/npm-publish.yml
    • .github/workflows/release.yml
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds a JSON-RPC CLI surface to cmd/docxgo and introduces a Node.js/TypeScript wrapper package under npm/, alongside CI workflows for multi-platform releases and npm publishing to support Issue #19’s integration plan.

Changes:

  • Expanded the Go CLI JSON-RPC protocol (new system/template/batch/patch + mutation methods) and updated CLI docs.
  • Added an npm package (@mmonterroca/docxgo) with RPC/exec clients, a fluent DocumentBuilder, protocol types, and Node tests.
  • Added GitHub Actions workflows for building release binaries and publishing platform-specific npm binary packages + main wrapper package.

Reviewed changes

Copilot reviewed 22 out of 28 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
npm/tsconfig.json TypeScript build configuration for the Node wrapper.
npm/src/types.ts Shared JSON-RPC protocol and document/content type definitions.
npm/src/rpc.ts Persistent NDJSON RPC client implementation + DocxgoError.
npm/src/index.ts Public entrypoint exports for the npm package.
npm/src/exec.ts Synchronous one-shot execution client.
npm/src/builder.ts Fluent builder API wrapping the RPC client.
npm/src/binary.ts Cross-platform binary resolution logic (optionalDependencies/local/PATH).
npm/src/__tests__/docxgo.test.ts Node integration tests across exec/RPC/builder/template/patch/batch.
npm/scripts/build-esm.js Generates an ESM wrapper (dist/index.mjs) over CJS output.
npm/platforms/win32-x64/.gitkeep Placeholder for Windows platform package directory.
npm/platforms/linux-x64/.gitkeep Placeholder for Linux x64 platform package directory.
npm/platforms/linux-arm64/.gitkeep Placeholder for Linux arm64 platform package directory.
npm/platforms/darwin-x64/.gitkeep Placeholder for macOS x64 platform package directory.
npm/platforms/darwin-arm64/.gitkeep Placeholder for macOS arm64 platform package directory.
npm/platforms/README.md Documentation for how platform binary npm packages are produced/published.
npm/platforms/.gitignore Ignores generated binaries and platform package manifests.
npm/package.json Defines the npm package, scripts, exports, and optionalDependencies.
npm/package-lock.json Lockfile for npm development dependencies and tooling.
npm/README.md Node wrapper documentation, examples, and API reference.
npm/.gitignore Ignores npm build artifacts (dist/, bin/, tarballs).
docs/CLI_GUIDE.md Protocol/method reference updates (system/template/batch/applyPatch/etc.).
cmd/docxgo/protocol.go Adds ProtocolVersion and enriches RPC errors with data.
cmd/docxgo/main.go Adds version --json output with capabilities and runtime info.
cmd/docxgo/handlers_test.go Adds extensive handler/unit/integration tests for new RPC methods.
cmd/docxgo/handlers.go Implements new RPC handlers (system., mutations, template., applyPatch).
.github/workflows/release.yml Builds multi-platform Go binaries on tag pushes and creates GH Releases.
.github/workflows/npm-publish.yml Publishes platform binary packages then the main npm wrapper package.
.github/workflows/ci.yml Updates CI branch filters and adds a Node.js test job.
Files not reviewed (1)
  • npm/package-lock.json: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Comment on lines +1093 to +1100
applied := 0
for i, raw := range params.Operations {
var pOp patchOperation
if err := json.Unmarshal(raw, &pOp); err != nil {
return errorResponseWithData(req.ID, errors.ErrCodeValidation,
fmt.Sprintf("invalid operation at index %d: %v", i, err), op,
map[string]interface{}{"index": i})
}

### document.applyPatch

Applies a sequence of patch operations to an existing document atomically. If any operation fails, subsequent operations are not applied and the error includes the failing index.
Comment on lines +496 to +500
* Operations are applied atomically — if any fails, subsequent ones
* are not applied and the error includes the failing index.
*
* @param operations Array of patch operations.
* @returns Result with count of applied operations.
npm/package.json Outdated
],
"scripts": {
"build": "tsc && node scripts/build-esm.js",
"test": "node --test dist/__tests__/*.test.js",
Comment on lines +126 to +145
return new Promise<T>((resolve, reject) => {
const id = ++this.seq;
const timeoutMs = timeout ?? this.defaultTimeout;

const timer = timeoutMs > 0
? setTimeout(() => {
this.pending.delete(id);
reject(new Error(`RPC call ${method} timed out after ${timeoutMs}ms`));
}, timeoutMs)
: undefined;

this.pending.set(id, {
resolve: resolve as (value: unknown) => void,
reject,
timer,
});

const req: RPCRequest = { id, method, params };
this.proc.stdin!.write(JSON.stringify(req) + '\n');
});
"name": "@mmonterroca/docxgo-${{ matrix.suffix }}",
"version": "${{ steps.version.outputs.version }}",
"description": "docxgo binary for ${{ matrix.suffix }}",
"os": ["${{ matrix.goos }}"],
"arch": runtime.GOARCH,
"features": capabilitiesMap(),
}
out, _ := json.MarshalIndent(info, "", " ")
Comment on lines +957 to +976
func (s *server) handleTemplateInspect(req *Request) Response {
const op = "template.inspect"

var params templateInspectParams
raw := req.Params
if len(raw) == 0 || bytes.Equal(bytes.TrimSpace(raw), []byte("null")) {
raw = []byte("{}")
}
if err := json.Unmarshal(raw, &params); err != nil {
return errorResponse(req.ID, errors.ErrCodeValidation, "invalid params: "+err.Error(), op)
}

doc, ok := s.getDoc(params.DocumentID)
if !ok {
return errorResponse(req.ID, errors.ErrCodeNotFound,
fmt.Sprintf("document %q not found", params.DocumentID), op)
}

placeholders := template.FindPlaceholders(doc)

- errcheck: add explicit _ = for unchecked returns in consolidate.go (12) and merge.go (1)
- errcheck: wrap deferred os.Remove in anonymous func in handlers.go
- staticcheck: convert if/else chain to switch on Orientation in handlers.go
- unparam: change runRPC() from int to void since it always returned 0
- unused: remove unused cleanup function and stale imports in example 15
Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request is a major feature addition, introducing a JSON-RPC wrapper for the docxgo library and a comprehensive Node.js integration package. The changes include new CLI commands, numerous RPC handlers in Go for document manipulation, templating, and batch operations, along with extensive test coverage. The Node.js package provides a well-designed, typed, and fluent API for interacting with the Go binary. The documentation has also been updated thoroughly. The overall quality of the implementation is very high. I have one suggestion to improve the API design of the document.applyPatch method for better clarity and to prevent potential misuse.

Comment on lines +1155 to +1175
case "setMetadata":
var mp setMetadataParams
if err := json.Unmarshal(raw, &mp); err != nil {
return errorResponseWithData(req.ID, errors.ErrCodeValidation,
fmt.Sprintf("invalid setMetadata at index %d: %v", i, err), op,
map[string]interface{}{"index": i})
}
meta := &domain.Metadata{
Title: mp.Title,
Subject: mp.Subject,
Creator: mp.Creator,
Description: mp.Description,
Keywords: mp.Keywords,
Created: mp.Created,
Modified: mp.Modified,
}
if err := doc.SetMetadata(meta); err != nil {
return errorResponseWithData(req.ID, errors.ErrCodeValidation,
fmt.Sprintf("failed to set metadata at index %d: %v", i, err), op,
map[string]interface{}{"index": i})
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

In the handleApplyPatch function, the setMetadata operation reuses the setMetadataParams struct. This struct includes a DocumentID field, which is redundant and potentially confusing within a patch operation, as the document ID is already provided at the applyPatch level. The DocumentID from the patch operation is parsed but ignored, which could mislead API users.

To improve API clarity and prevent misuse, I suggest defining a specific struct for the setMetadata patch operation that omits the DocumentID, similar to how the setBackgroundColor operation is handled using a local anonymous struct. This would make the API contract more explicit.

case "setMetadata":
	var mp struct {
		Title       string   `json:"title,omitempty"`
		Subject     string   `json:"subject,omitempty"`
		Creator     string   `json:"creator,omitempty"`
		Description string   `json:"description,omitempty"`
		Keywords    []string `json:"keywords,omitempty"`
		Created     string   `json:"created,omitempty"`
		Modified    string   `json:"modified,omitempty"`
	}
	if err := json.Unmarshal(raw, &mp); err != nil {
		return errorResponseWithData(req.ID, errors.ErrCodeValidation,
			fmt.Sprintf("invalid setMetadata at index %d: %v", i, err), op,
			map[string]interface{}{"index": i})
	}
	meta := &domain.Metadata{
		Title:       mp.Title,
		Subject:     mp.Subject,
		Creator:     mp.Creator,
		Description: mp.Description,
		Keywords:    mp.Keywords,
		Created:     mp.Created,
		Modified:    mp.Modified,
	}
	if err := doc.SetMetadata(meta); err != nil {
		return errorResponseWithData(req.ID, errors.ErrCodeValidation,
			fmt.Sprintf("failed to set metadata at index %d: %v", i, err), op,
			map[string]interface{}{"index": i})
	}

- Fix atomicity claim: docs and docstrings now describe sequential fail-fast
  behavior with no rollback instead of atomic guarantees
- Fix template.inspect: now honors openDelimiter/closeDelimiter params via
  FindPlaceholdersCustom + exported BuildPattern
- Fix setMetadata in applyPatch: use anonymous struct without redundant DocumentID
- Fix main.go: handle json.MarshalIndent error instead of discarding it
- Fix rpc.ts: wrap stdin.write in try/catch to prevent pending map leaks
- Fix npm-publish.yml: map Go 'windows' to npm 'win32' for os field
- Fix npm test script: run source tests via tsx instead of compiled dist
The reader extracted CoreProperties bytes from the zip but never populated
the document's Metadata struct during reconstruction. This meant that
metadata (title, creator, subject, etc.) set before saving was lost when
the document was re-opened.

- Add parseCoreProperties() in reconstruct.go with namespace-aware XML
  struct (Go's encoding/xml resolves prefixes to URIs during decode)
- Call doc.SetMetadata() during ReconstructDocument after preserveOriginalParts
- Add TestMetadataRoundTrip test verifying write → reopen → read cycle
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR implements Issue #19 by adding a JSON-RPC CLI layer to docxgo, publishing a TypeScript/Node.js wrapper (npm/), and wiring up CI workflows for multi-platform binary releases and npm publishing.

Changes:

  • Added/expanded Go CLI JSON-RPC protocol, handlers, and tests (including new namespaces like system.*, mutation methods, template methods, and batch requests).
  • Introduced a TypeScript Node.js client package with exec + persistent RPC + fluent builder APIs, plus protocol typings and tests.
  • Added CI/CD workflows for Go binary releases, npm publishing (including platform packages), and Node test execution.

Reviewed changes

Copilot reviewed 28 out of 34 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
pkg/template/merge.go Exposes pattern builder and adjusts run text-setting during template merge.
pkg/template/consolidate.go Updates run consolidation to use error-returning run setters.
npm/tsconfig.json Adds TypeScript compiler configuration for the Node wrapper package.
npm/src/types.ts Defines the JSON-RPC protocol + document/content/template/patch TypeScript types.
npm/src/rpc.ts Implements persistent NDJSON JSON-RPC client and error type for Node.
npm/src/index.ts Exports Node wrapper public API (clients, builder, binary resolver, types).
npm/src/exec.ts Implements one-shot synchronous exec-based JSON-RPC client.
npm/src/builder.ts Adds fluent builder API atop the persistent RPC client.
npm/src/binary.ts Implements cross-platform binary resolution via optionalDependencies/env/PATH.
npm/src/tests/docxgo.test.ts Adds Node integration tests covering exec/rpc/builder/template/batch/patch flows.
npm/scripts/build-esm.js Generates an ESM wrapper entrypoint from CJS build output.
npm/platforms/win32-x64/.gitkeep Placeholder for platform package directory.
npm/platforms/linux-x64/.gitkeep Placeholder for platform package directory.
npm/platforms/linux-arm64/.gitkeep Placeholder for platform package directory.
npm/platforms/darwin-x64/.gitkeep Placeholder for platform package directory.
npm/platforms/darwin-arm64/.gitkeep Placeholder for platform package directory.
npm/platforms/README.md Documents how platform-specific npm binary packages work.
npm/platforms/.gitignore Ignores platform-package build artifacts (binaries, generated package.json).
npm/package.json Defines @mmonterroca/docxgo package metadata, exports, scripts, optionalDependencies.
npm/package-lock.json Locks Node dev dependency tree for the npm package.
npm/README.md Adds Node wrapper documentation, examples, and API reference.
npm/.gitignore Ignores npm build/test artifacts (node_modules, dist, bin, tarballs).
internal/reader/reconstruct.go Hydrates document metadata from core properties to preserve round-trip metadata.
examples/15_external_template/main.go Removes output cleanup logic from the external template example.
docx_read_test.go Adds a Go test validating metadata round-trip behavior.
docs/CLI_GUIDE.md Expands CLI protocol documentation for new RPC methods and enriched errors.
cmd/docxgo/rpc.go Adjusts RPC runner signature/exit behavior for persistent mode.
cmd/docxgo/protocol.go Adds protocol version constant and enriched error data support.
cmd/docxgo/main.go Extends CLI version command to support --json + capabilities output.
cmd/docxgo/handlers_test.go Adds extensive handler tests for mutation/template/batch/applyPatch/system namespaces.
cmd/docxgo/handlers.go Implements new RPC handlers for system, mutation, template, and patch operations.
.github/workflows/release.yml Adds multi-platform Go binary build + GitHub Release publishing workflow.
.github/workflows/npm-publish.yml Adds release-triggered npm publish workflow for platform packages + main package.
.github/workflows/ci.yml Updates branch filters and adds a Node.js test job building the Go CLI binary.
Files not reviewed (1)
  • npm/package-lock.json: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Comment on lines +52 to +56
stdout = execFileSync(this.binPath, ['exec', '--request', requestJSON], {
timeout: timeout ?? this.defaultTimeout,
encoding: 'utf-8',
stdio: ['pipe', 'pipe', 'pipe'],
});
Comment on lines +472 to +485
## Development

```bash
# Install dependencies
cd npm && npm install

# Run tests (TypeScript, no build needed)
npm run test:src

# Build (CJS + ESM)
npm run build

# Type-check
npm run lint
Comment on lines +1048 to +1060
// Validate first
validationErrors := template.ValidateTemplate(doc, template.MergeData(params.Data), opts)
var warnings []map[string]interface{}
for _, ve := range validationErrors {
sev := "error"
if ve.Severity == template.SeverityWarning {
sev = "warning"
}
warnings = append(warnings, map[string]interface{}{
"severity": sev,
"key": ve.Key,
"message": ve.Message,
})
Comment on lines 112 to 116
if newText != text {
run.SetText(newText)
_ = run.SetText(newText)
// Clear fields on this run if it has any.
if len(run.Fields()) > 0 {
run.ClearFields()
Comment on lines +58 to +66
_ = r.SetText(m.text)
_ = r.SetFont(m.src.Font())
_ = r.SetColor(m.src.Color())
_ = r.SetSize(m.src.Size())
_ = r.SetBold(m.src.Bold())
_ = r.SetItalic(m.src.Italic())
_ = r.SetUnderline(m.src.Underline())
_ = r.SetStrike(m.src.Strike())
_ = r.SetHighlight(m.src.Highlight())
// Hydrate metadata from docProps/core.xml so it survives round-trip.
if parsed.Package != nil && len(parsed.Package.CoreProperties) > 0 {
if meta, err := parseCoreProperties(parsed.Package.CoreProperties); err == nil && meta != nil {
_ = doc.SetMetadata(meta)
Comment on lines +2133 to +2135
meta.Keywords = strings.Split(cp.Keywords, ",")
for i := range meta.Keywords {
meta.Keywords[i] = strings.TrimSpace(meta.Keywords[i])
The paragraphItem struct only had a 'runs' array, so passing
{"text": "Hello"} was silently ignored — no error but no text
rendered in the document either.

Add a 'text' shortcut field that auto-creates a single run when
no explicit runs are provided. This makes the simple case ergonomic
while preserving full runs array support for formatted text.
- 01_basic: headings, formatted text, multi-run paragraphs
- 02_tables_and_sections: tables, page breaks, landscape sections
- 03_read_modify: open → inspect → add content → save workflow
- 04_template: mail merge with {{placeholders}}, inspect, render
- 05_patch_and_system: applyPatch, batch, metadata, system info

All 5 examples validated: 8 .docx files generated, all valid
Microsoft Word 2007+ format. Run with: bash npm/examples/run_all.sh
- exec.ts: set maxBuffer to 50MB to prevent crash on large documents
- README.md: fix test:src reference to npm test
- handlers.go: downgrade validation severity to warning/info in non-strict
  template.render (avoid mixing error severity with ok:true responses)
- merge.go: propagate run.SetText error instead of ignoring it
- reconstruct.go: propagate SetMetadata error, filter empty keywords
- Add text shortcut to AppendParagraphOp type
- Add errors array to ValidateResult type
- Change TemplateWarning severity to warning|info (matches handler)
- Use optional chaining for info.metadata in examples
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement CLI JSON-RPC wrapper for docxgo and Node.js integration

2 participants