{"_id":"@asi-ai/article-format-extractor","name":"@asi-ai/article-format-extractor","dist-tags":{"latest":"0.1.0"},"versions":{"0.1.0":{"name":"@asi-ai/article-format-extractor","version":"0.1.0","description":"Deterministic DOCX format profile extractor for Node.js and CLI workflows.","type":"module","license":"MIT","publishConfig":{"access":"public"},"bin":{"article-format-extractor":"dist/cli/index.js"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./schema":{"types":"./dist/schema.d.ts","import":"./dist/schema.js"},"./schema.json":{"default":"./schemas/document-format-profile.schema.json"}},"scripts":{"build":"tsup src/index.ts src/cli/index.ts src/schema.ts --format esm --dts --sourcemap --clean","prepack":"npm test && npm run typecheck && npm run build","test":"vitest run","typecheck":"tsc --noEmit"},"dependencies":{"ajv":"^8.17.1","commander":"^14.0.2","fast-xml-parser":"^5.3.0","jszip":"^3.10.1"},"devDependencies":{"@types/node":"^24.10.1","tsup":"^8.5.1","typescript":"^5.9.3","vitest":"^4.0.15"},"engines":{"node":">=20"},"gitHead":"f21337e7f66e54d7e0b330bcc3f880cddeb72050","_id":"@asi-ai/article-format-extractor@0.1.0","_nodeVersion":"24.15.0","_npmVersion":"11.12.1","dist":{"integrity":"sha512-AmwiRBl9tVxj8h7H5BVC03hH9Y/4cQ/qd407FI3gvgKVEbpNdsB1rArHSIDzxthdfRhVXOGNjALIPhzAAEzMSw==","shasum":"314fe81b8c4be89e977e546bfa54c6216ec540d4","tarball":"https://registry.npmjs.org/@asi-ai/article-format-extractor/-/article-format-extractor-0.1.0.tgz","fileCount":17,"unpackedSize":158011,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIBMA0Uzr0RJGw72PG79y8/OLB/1mcx+58FRuup4XlpROAiEAwyrrOplEJICxDfjO+tMCU8HhqjLw82kBKQFsfYGAwCI="}]},"_npmUser":{"name":"zongzack","email":"zongzack@outlook.com"},"directories":{},"maintainers":[{"name":"zongzack","email":"zongzack@outlook.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/article-format-extractor_0.1.0_1781692460036_0.23756341110577628"},"_hasShrinkwrap":false}},"time":{"created":"2026-06-17T10:34:19.810Z","0.1.0":"2026-06-17T10:34:20.179Z","modified":"2026-06-17T10:34:20.455Z"},"maintainers":[{"name":"zongzack","email":"zongzack@outlook.com"}],"description":"Deterministic DOCX format profile extractor for Node.js and CLI workflows.","license":"MIT","readme":"# @asi-ai/article-format-extractor\n\n面向 Node.js 和命令行工作流的 DOCX 确定性格式画像提取工具。\n\n本包读取 DOCX OpenXML 文件，输出稳定的 `DocumentFormatProfile` JSON，用于描述页面设置、标题样式、正文段落样式、编号定义等格式事实。\n\n它适合作为格式库、格式对比、合同/文档格式检查，以及后续自动修订流程的底层基础能力。\n\n## 功能特性\n\n- 仅支持 DOCX，基于 OpenXML package parts 解析。\n- 同时提供 Node API 和 CLI。\n- 输出稳定的 `schemaVersion: \"1.0.0\"`。\n- 提供 JSON Schema，用于校验提取结果。\n- 提供结构化 `warning` 和 `error` 契约。\n- 对确定性格式事实保留 evidence ID。\n- 输出结果稳定，适合 snapshot、golden test 和批处理。\n\n## 支持范围\n\n当前 1.0 版本聚焦 DOCX 中可确定读取的格式事实：\n\n- `word/document.xml`\n- `word/styles.xml`\n- `word/numbering.xml`\n- section properties\n\n当前版本不解析 PDF、Markdown、HTML、图片、URL、OCR、语义章节，也不尝试完整复刻 Word 渲染结果。\n\n## 安装\n\n```bash\nnpm install @asi-ai/article-format-extractor\n```\n\n要求 Node.js 20 或更高版本。\n\n## CLI 使用\n\n```bash\narticle-format-extractor input.docx\n```\n\n格式化输出 JSON：\n\n```bash\narticle-format-extractor input.docx --pretty\n```\n\n写入到指定文件：\n\n```bash\narticle-format-extractor input.docx --output profile.json --pretty\n```\n\n输出 raw OpenXML 片段，便于调试：\n\n```bash\narticle-format-extractor input.docx --include-raw\n```\n\n关闭正文示例：\n\n```bash\narticle-format-extractor input.docx --include-examples false\n```\n\n### CLI 输出规则\n\n成功且未传 `--output` 时，stdout 输出 `DocumentFormatProfile` JSON。\n\n成功且传入 `--output` 时，stdout 为空，JSON 写入指定文件。\n\nwarning 和 error 会以 JSON Lines 形式写入 stderr：\n\n```json\n{ \"type\": \"warning\", \"warning\": { \"code\": \"MULTIPLE_SECTIONS_NOT_FULLY_SUPPORTED\" } }\n{ \"type\": \"error\", \"error\": { \"code\": \"UNSUPPORTED_FILE_TYPE\" } }\n```\n\n退出码：\n\n| 退出码 | 含义 |\n| --- | --- |\n| `0` | 成功 |\n| `1` | 内部错误或 schema 校验失败 |\n| `2` | 用户输入或参数错误 |\n| `3` | 文档读取或解析失败 |\n\n## Node API\n\n```ts\nimport { extractDocumentFormat } from '@asi-ai/article-format-extractor';\n\nconst result = await extractDocumentFormat({\n  type: 'path',\n  path: '/path/to/input.docx',\n});\n\nif (result.ok) {\n  console.log(result.profile);\n  console.log(result.warnings);\n} else {\n  console.error(result.error);\n}\n```\n\n使用 Buffer 输入：\n\n```ts\nimport { readFile } from 'node:fs/promises';\nimport { extractDocumentFormat } from '@asi-ai/article-format-extractor';\n\nconst data = await readFile('/path/to/input.docx');\nconst result = await extractDocumentFormat({\n  type: 'buffer',\n  data,\n  fileName: 'input.docx',\n});\n```\n\n可选参数：\n\n```ts\nconst result = await extractDocumentFormat(input, {\n  parser: 'docx-openxml',\n  includeRaw: false,\n  includeExamples: true,\n  timeoutMs: 30_000,\n});\n```\n\n## Schema\n\n导入内置 schema：\n\n```ts\nimport { documentFormatProfileSchema } from '@asi-ai/article-format-extractor/schema';\n```\n\n也可以直接引用 JSON 文件子路径：\n\n```ts\nimport schema from '@asi-ai/article-format-extractor/schema.json' with { type: 'json' };\n```\n\n包内也导出了便捷校验函数：\n\n```ts\nimport { validateDocumentFormatProfile } from '@asi-ai/article-format-extractor';\n\nconst validation = validateDocumentFormatProfile(profile);\nif (!validation.ok) {\n  console.error(validation.errors);\n}\n```\n\n## 输出结构\n\n成功提取时返回：\n\n```ts\ntype ExtractResult =\n  | {\n      ok: true;\n      profile: DocumentFormatProfile;\n      warnings: FormatWarning[];\n    }\n  | {\n      ok: false;\n      error: FormatError;\n      warnings: FormatWarning[];\n      partialProfile?: DocumentFormatProfile;\n    };\n```\n\n`profile` 包含以下核心字段：\n\n| 字段 | 说明 |\n| --- | --- |\n| `schemaVersion` | 固定为 `\"1.0.0\"` |\n| `source` | 输入来源信息，例如输入类型、文件名、MIME type、文件大小 |\n| `parser` | 解析器名称和确定性模式 |\n| `confidence` | RuleValue 置信度的聚合结果 |\n| `page` | 可读取时输出纸张大小、方向、页边距 |\n| `headingStyles` | 确定性标题样式事实 |\n| `paragraphStyles` | 正文段落样式事实 |\n| `listStyles` | 来自 `word/numbering.xml` 的编号定义 |\n| `evidence` | 被格式事实引用的稳定证据记录 |\n| `raw` | 开启 `includeRaw` 后输出的可选调试数据 |\n\n## 输出片段示例\n\n```json\n{\n  \"schemaVersion\": \"1.0.0\",\n  \"parser\": {\n    \"name\": \"docx-openxml\",\n    \"version\": \"0.1.0\",\n    \"mode\": \"deterministic\"\n  },\n  \"paragraphStyles\": [\n    {\n      \"role\": \"body\",\n      \"styleId\": \"Normal\",\n      \"evidenceIds\": [\"ev:word_document:paragraph_0:body_role\"],\n      \"examples\": []\n    }\n  ],\n  \"listStyles\": [],\n  \"evidence\": []\n}\n```\n\n## Warning\n\nwarning 表示可恢复的降级，不会导致 `result.ok` 变为 `false`。\n\n常见 warning code：\n\n| Code | 含义 |\n| --- | --- |\n| `STYLES_PART_MISSING` | 缺少 `word/styles.xml` |\n| `STYLES_PART_UNREADABLE` | `word/styles.xml` 无法解析 |\n| `NUMBERING_PART_UNREADABLE` | `word/numbering.xml` 无法解析 |\n| `SECTION_PROPERTIES_MISSING` | 未找到可读 section properties |\n| `MULTIPLE_SECTIONS_NOT_FULLY_SUPPORTED` | 文档存在多个 section，当前只输出第一个可读 section |\n| `UNSUPPORTED_STYLE_FEATURE` | 遇到 1.0 确定性子集之外的样式特性 |\n| `RAW_OUTPUT_CONTAINS_SOURCE_CONTENT` | raw 输出可能包含源文档内容 |\n\n## Error\n\n致命失败会返回 `ok: false` 和稳定错误码。\n\n常见 error code：\n\n| Code | 含义 |\n| --- | --- |\n| `UNSUPPORTED_INPUT_TYPE` | 输入类型不是 `path` 或 `buffer` |\n| `UNSUPPORTED_FILE_TYPE` | 输入不是 DOCX 文档 |\n| `UNSUPPORTED_PARSER` | 指定 parser 不受支持 |\n| `FILE_NOT_FOUND` | 输入路径不存在 |\n| `INPUT_TOO_LARGE` | 输入超过配置限制 |\n| `DOCX_CORRUPTED` | DOCX 压缩包损坏或不可读 |\n| `DOCX_ENCRYPTED` | DOCX 疑似加密 |\n| `XML_PARSE_FAILED` | 必需 XML part 无法解析 |\n| `REQUIRED_PART_MISSING` | 缺少必需 OpenXML part |\n| `EMPTY_DOCUMENT` | 未找到可解析的正文段落 |\n| `PARSER_TIMEOUT` | 解析超过配置的超时时间 |\n| `ZIP_BOMB_SUSPECTED` | 压缩包展开行为异常，疑似 zip bomb |\n| `SCHEMA_VALIDATION_FAILED` | 内部输出未通过 schema 校验 |\n\n## 本地开发\n\n安装依赖：\n\n```bash\nnpm install\n```\n\n运行测试：\n\n```bash\nnpm test\n```\n\n类型检查：\n\n```bash\nnpm run typecheck\n```\n\n构建：\n\n```bash\nnpm run build\n```\n\n预览 npm 包内容：\n\n```bash\nnpm pack --dry-run\n```\n\n## 发布\n\n当前包配置为公开 scoped package：\n\n```bash\nnpm publish --access public\n```\n\n`prepack` 脚本会在打包或发布前自动执行测试、类型检查和构建。\n\n## License\n\nMIT\n","readmeFilename":"README.md","_rev":"1-5e7eaf8ece7fc387135b742cd6b9931b"}