Skip to content

About

本地导出 PDF、Word、Markdown 报告与版本记录表格,保留来源和长字段。 / Local PDF, Word and Markdown reports plus versioned record workbooks, retaining references and long fields.

Topics

Resources

Contributing

Stars

2 stars

Watchers

0 watching

Forks

Repository files navigation

Report Export Kit · 结构化报告导出工具

English · 简体中文

CI · MIT · Node.js 22.12+

Turn structured content into a readable PDF, editable Word document and portable Markdown—locally, from the same input.

Your research script or agent has produced useful text, tables and charts. Report Export Kit handles the delivery: define a small JSON document, keep its source references, and render three formats without rewriting the content. It is suitable for research notes, operational briefs and agent-generated reports that need to leave the chat window.

No model, account or API key is required. The renderer never fetches source URLs or sends report content to a service.

Actual bilingual synthetic report generated by the kit

Recent example / 新增示例

新增记录表格导出:读取调用者提供的版本快照,将长字段分段保留,并按文本写入单元格;详见下方接口说明。

New: exportRecordWorkbook(records) exports a supplied versioned snapshot to XLSX (Records, Fields, Manifest). Each record needs id, version, and a JSON fields object; optional source is caller-provided text. Run node examples/records.js for a fictional long-text example. All user cells are text, including = prefixes. Long fields split into ordered parts with JSON Pointer paths; join them by record/version/path and numeric Part. No fetching or latest-version substitution occurs. Limits: 1000 records, 50000 field parts, 10 MB input. Invalid XML characters are rejected. Output contains your supplied data. This record API is separate from the three report-rendering formats below.

Contents

Useful starting points

Workflow What you provide What you can deliver
Research brief Reviewed prose, observation tables and references A readable PDF plus an editable Word copy
Weekly operations note A stable JSON document produced by a script The same content in three formats
Agent report delivery Agent output mapped to validated blocks Downloadable files with a source list and version

The input remains your content: the exporter does not call a model to rewrite paragraphs, invent a chart interpretation or fetch linked evidence. This makes the rendering step easy to repeat and review separately from research and writing.

Try a complete example

Requires Node.js 22.12+. In this project folder:

git clone https://github.com/workstonedai-collab/report-export-kit.git
cd report-export-kit
npm ci
npm run demo

Open output/demo.pdf, output/demo.docx and output/demo.md. The demo includes Chinese/English prose, a data table, a locally drawn PNG chart and an example source. All numbers and conclusions are invented. Markdown's chart is saved alongside it as figure-1.png.

The unmodified Noto Sans CJK SC font and its OFL license are included for Chinese PDF text. If the font is absent, npm run setup-font retrieves it from the official Noto repository. You can also pass your own compatible font using fontPath.

The document contract

import { exportReport } from './src/index.js';
import fs from 'node:fs/promises';

const report = {
  title: 'Weekly notes / 每周笔记', version: 1,
  blocks: [
    { type: 'heading', text: 'Findings / 发现' },
    { type: 'paragraph', text: 'Your own reviewed content.' },
    { type: 'table', headers: ['Period', 'Value'], rows: [['2025', 12]] },
  ],
  sources: [{ title: 'Your source', url: 'https://example.org/data' }],
};
const file = await exportReport(report, 'pdf');
await fs.writeFile('report.pdf', file.content);
Block Required data Notes
heading text Optional level 1–3
paragraph text Plain text, including line breaks
table headers, rows Every row must match header width; optional title/note
image PNG base64 data Optional title/note; dimensions are read from PNG

Top-level fields: title, optional positive integer version, subtitle, blocks, sources. Sources require a title and HTTP(S) URL, with optional publisher/date. They are a document reference list; this renderer does not establish claim-level evidence or verify the source.

For Markdown, write every returned assets item next to the .md file. exportReport also returns byte count, version and output SHA-256. The hash identifies a particular generated file; PDF metadata can make separately generated files differ.

Command-line use

node src/cli.js your-report.json output

This writes report.pdf, report.docx, report.md and Markdown image assets. An optional third argument is a font path. The output directory is yours to manage; running again replaces the files with these fixed names.

Start your own report from the included JSON

A small editable input is included at examples/report.json. You can render it directly:

npm run export -- examples/report.json output/my-report

Change the title, paragraphs, rows and sources in a copy of that file, then run the same command with your file path. It writes three files named report.pdf, report.docx, report.md; a report with images also writes Markdown sidecar PNGs. Keep the .md and those images together when sharing them.

For library use, save each format and its image assets explicitly:

import fs from 'node:fs/promises';
import path from 'node:path';
import { exportReport } from './src/index.js';

const report = JSON.parse(await fs.readFile('examples/report.json', 'utf8'));
const directory = 'output/my-report';
await fs.mkdir(directory, { recursive: true });
for (const format of ['pdf', 'docx', 'md']) {
  const result = await exportReport(report, format);
  await fs.writeFile(path.join(directory, `report.${format}`), result.content);
  for (const asset of result.assets) {
    await fs.writeFile(path.join(directory, asset.filename), asset.content);
  }
  console.log(format, result.bytes, result.version, result.sha256);
}

Use a different output directory per report when preserving history. A document version labels the supplied content; the library does not maintain a revision database.

Add a chart or your own font

For a PNG you already have, supply its base64 bytes in an image block:

const data = (await fs.readFile('your-chart.png')).toString('base64');
report.blocks.push({ type: 'image', data,
  title: 'Your chart', note: 'State units, exact values and provenance here.' });

The small barChart helper draws non-negative values locally. Add exact labels, units and values in a table or caption. Negative values, interactive plots and remote images are not supported by that helper; create a suitable PNG with your preferred chart tool instead.

To change the PDF font, pass exportReport(report, 'pdf', { fontPath: './your-font.ttf' }), or use the CLI's third argument. Use a font that covers every script in your text and whose terms permit your use. Word readers need a compatible font on the receiving computer.

Troubleshooting

Symptom What to check
Chinese PDF text fails or is missing Confirm the bundled font exists or supply a compatible fontPath; npm run setup-font restores the official font if needed
A table is rejected Every row must have exactly the same number of cells as headers; use finite numbers or strings
Markdown has a broken chart Save the returned assets beside the Markdown, retaining their filenames
A source is rejected Supply a title and a valid HTTP(S) URL
Word looks different from the PDF It is a reflowable document; check local fonts and your office application's page layout
Output was replaced The CLI uses fixed filenames; separate report versions into different directories

What the first release does well

  • One validated document contract for three delivery formats.
  • Chinese/English PDF text with an included open font.
  • True Word tables and embedded PNG images.
  • Multi-page PDF tables with repeated headers; large row content falls back to labeled paragraphs.
  • Clear source references, versioned content and output hashes.
  • A tiny local PNG bar-chart helper in src/charts.js; exact labels, units and values belong in the adjacent table or caption.

Scope and limitations

This is a structured report renderer, not an arbitrary HTML/Markdown importer, office-template editor or document parser. PNG is the supported image format. Heading/paragraph blocks use plain text. Word's exact layout depends on the receiving office application and fonts; the font is referenced rather than embedded in DOCX. PDF output uses A4 pages and a simple editorial layout.

Validation catches malformed blocks and unsupported URLs; it does not validate factual accuracy. Review the source content before exporting. Large documents and images have bounded sizes. All processing is local, but the files you produce can contain whatever private content you supplied.

Development

npm test

Tests cover three formats, input immutability, source/table validation and multi-page bilingual PDF output. The example PDF was also reopened for Chinese text/reference checks and visually rendered. CI is configured for Node 22/24 on three desktop OS families.

See THIRD-PARTY-NOTICES.md for the Noto font and dependencies, and CONTRIBUTING.md for contributions. Project code is licensed under MIT. Third-party dependencies and data retain their own terms.

About

本地导出 PDF、Word、Markdown 报告与版本记录表格,保留来源和长字段。 / Local PDF, Word and Markdown reports plus versioned record workbooks, retaining references and long fields.

Topics

Resources

Contributing

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages