@bendyline/squisq-formats (中文(简体) )
Squisq 的文档格式转换器。 在斯奎斯克基于Markdown的文档模式和常见文件格式之间导入和导出——DOCX,PDF,HTML,EPUB,PPTX,XLSX,和CSV. 所有转换器都在浏览器或节点中运行,不需要服务器或本地二进制.
部分 斯奎斯克语Name 单相机.
安装
npm install @bendyline/squisq-formats @bendyline/squisq
转换方式
所有转换器都使用 Squisq 的 MarkdownDocument AST(从 @bendyline/squisq/markdown)作为枢轴格式:
- 导入 将文件解析为
MarkdownDocument编辑xxxToContainer变体(DOCX、PDF、PPTX)还将嵌入式图像提取到一个ContentContainer与减分. - 导出 序列化 a
MarkdownDocument打开目标格式。 每种格式还有一个docToXxx编号 :xxxToDoc转换到MarkdownDocument内部.
转换保留了文档结构和来源的大部分口味——标题、文本格式、列表、表格、链接、图像,但它们是 不是无损失的回程. 下文列出每个格式的忠诚限度.
所有接受 themeId (DOCX,PDF,EPUB,PPTX,Plain HTML) 应用斯奎斯克主题颜色/打字法,并倒回了道克的前题主题(英语:squisq-theme 编号 : themeId 编号 : theme 键),当该选项被省略时.
对于每个转换器上的统一、格式不可识别的切入点,请使用 格式登记册 财务报告和审定财务报表 convert() (单位:千美元)@bendyline/squisq-formats/registry)——见 程序化 convert() 见下文.
支持的格式
| 格式 | 导入 | 导出 | 主题 | 子路径 |
|---|---|---|---|---|
| DOCX 数据库 (恶语) | ✅ | ✅ | ✅ | @bendyline/squisq-formats/docx |
| 专题报告 | ✅ | ✅ | ✅ | @bendyline/squisq-formats/pdf |
| HTML 语言 | ✅ | ✅ | ✅ | @bendyline/squisq-formats/html |
| 联布办事处 (电子书) | —— 说 | ✅ | ✅ | @bendyline/squisq-formats/epub |
| PPTX 密码 (PowerPoint) (英语) | ✅ | ✅ | ✅ | @bendyline/squisq-formats/pptx |
| XLSX 密码 (外语) | ✅ | 页:1 | —— 说 | @bendyline/squisq-formats/xlsx |
| 简历 | ✅ | ✅ | —— 说 | @bendyline/squisq-formats/csv |
| 集装箱 ZIP | ✅ | ✅ | —— 说 | @bendyline/squisq-formats/container |
1 XLSX 导出为 仅限表格 (v1.5)——见 XLSX 密码 节.
快速示例
DOCX 数据库
import {
markdownDocToDocx,
docxToMarkdownDoc,
docxToContainer,
} from '@bendyline/squisq-formats/docx';
// Export: MarkdownDocument → DOCX (ArrayBuffer)
const docxBytes = await markdownDocToDocx(markdownDoc, { title: 'Report', themeId: 'documentary' });
// Import: DOCX (ArrayBuffer | Blob) → MarkdownDocument
const imported = await docxToMarkdownDoc(docxBuffer, { extractImages: true });
// Import with assets: DOCX → ContentContainer (markdown + images/ files)
const container = await docxToContainer(docxBuffer);
忠诚: 导入涵盖标题、段落、内置格式(粗体、斜体、切换、内置代码)、超链接、列表、表格、块引文、代码块、脚注和嵌入式图像(通过 extractImages永远 docxToContainer) (中文(简体) ). 导出嵌入图像时只能通过 options.images;否则,它们作为占位符文本出现.
专题报告
import {
markdownDocToPdf,
pdfToMarkdownDoc,
pdfToContainer,
configurePdfWorker,
} from '@bendyline/squisq-formats/pdf';
// Configure the PDF.js worker (needed for import in some environments)
configurePdfWorker('/pdf.worker.min.mjs');
// Export: MarkdownDocument → PDF (ArrayBuffer)
const pdfBytes = await markdownDocToPdf(markdownDoc, { pageSize: 'a4' });
// Import: PDF → MarkdownDocument (heuristic structure detection)
const imported = await pdfToMarkdownDoc(pdfBuffer);
// Import with assets: PDF → ContentContainer (markdown + extracted images)
const container = await pdfToContainer(pdfBuffer);
忠诚: 导出使用pdf-lib的标准14字体(themeId 仅影响颜色)。 他们无法编码的文字——希腊语,西里尔语,越南语,箭头,数学,框图,符号——用嵌入的Unicode字体来绘制:被捆绑的DejaVu Sans面相,外加单色的Noto Emoji,Noto Sans SC和Noto Sans KR,用于emoji,中文,日文和韩文,每个都只为需要它而加载并分集的文档unicodeFonts 供给自己的脸,或 false 关掉这个). 这些封面,如泰文等,都没有被替换,一次通过 onWarning. 中日两行字符间断. 换行符 <br> (一个表格单元格唯一可控的行间断),表格列按其内容大小,一个单词对于其行间或字符间的单元格间断太长. 页面保持白色用于打印. 主题文本、标题和链接颜色在遇到4.5:1时与白纸和阴影表头相对照;否则出口商会使用其默认的暗墨来取用这一角色。 这也适用于继承主题和自定义主题. 过 images (由下调的 URL 键入, 如 DOCX 键入) 绘制 PNG 和 JPEG 图像, 在段落中单独显示; 其他图像打印为 [Image: alt] 注释。 PDF 没有语义结构, 因此导入时具有弹性和最佳效果: 标题由字体大小检测出, 表格 / 代码块 / 块 / 链接通过 detectTables 编号 : detectCodeBlocks 编号 : detectBlockquotes 编号 : detectLinks 选项(所有默认为真). pdfToMarkdownDoc 仅为文本; pdfToContainer 还在浏览器和节点中提取嵌入式 XObject 和内置光栅图像,放置 按页数 ——每个图像被插入到其页面上最后一个内容块后(仅图像的页面会倒回最接近的上一个有内容的页面,否则文件端). PDF.js 不能曝光的图像, 因为解码像素不会被释放.
图表作为图片
DOCX, EPUB, PDF 和 PPTX 无法绘制美人鱼图或 Squisq 图表, 因此
拥有它们导出图表源为文本 . rasterizeDiagrams 找到每个
图表-人鱼围栏,ASCII diagram编号 :timeline编号 :tree 围栏,以及
{[drawing]}编号 :{[layout]}编号 :{[diagram]} 标题块 - 请求渲染器
a 每一图的PNG,并用每个图替换返回文档
图像加出口商的字节 images 选项。 绘图需要a
浏览器; @bendyline/squisq-react/diagram-pictures 提供渲染器.
import { rasterizeDiagrams } from '@bendyline/squisq-formats/diagrams';
import { createDiagramPictureRenderer } from '@bendyline/squisq-react/diagram-pictures';
const pictured = await rasterizeDiagrams(markdownDoc, createDiagramPictureRenderer());
const docx = await markdownDocToDocx(pictured.markdownDoc, { images: pictured.images });
const pdf = await markdownDocToPdf(pictured.markdownDoc, { images: pictured.images });
// PPTX keeps drawings, timelines and ASCII diagrams as native shapes;
// only Mermaid needs a picture.
const pptx = await docToPptx(doc, { diagramImages: pictured.mermaid });
图形化器无法绘制为源; 导出从未失败
这个 图像条目带有其显示大小( E)width编号 :height 在 CSS 像素中,
照片在2x打印到1x.
HTML 语言
import { PLAYER_BUNDLE } from '@bendyline/squisq-react/standalone-source';
import {
docToHtml,
docToHtmlZip,
markdownDocToPlainHtml,
htmlToMarkdownDoc,
} from '@bendyline/squisq-formats/html';
// Interactive player export: Doc → single self-contained HTML string
// (player inlined, images as data URIs, timer-based playback — no audio)
const html = docToHtml(doc, { playerScript: PLAYER_BUNDLE, images });
// Interactive player export: Doc → ZIP Blob (external assets + optional audio)
const zipBlob = await docToHtmlZip(doc, { playerScript: PLAYER_BUNDLE, images, audio });
// Static export: MarkdownDocument → semantic HTML page (no player)
const page = markdownDocToPlainHtml(markdownDoc, { themeId: 'warm-earth' });
// Import: HTML → MarkdownDocument (sanitized by default)
const imported = await htmlToMarkdownDoc(htmlString);
将一个文档放在自己的页面内——一个站点头、导航、页脚和样式表——将页面写成带有标准的HTML模板 <slot> 元素并填入:
import { applyHtmlPageTemplate, markdownDocToPlainHtmlParts } from '@bendyline/squisq-formats/html';
// template: <title><slot name="title">Post</slot> · My Blog</title> … <h1><slot name="title"></slot></h1> <slot></slot>
const parts = markdownDocToPlainHtmlParts(markdownDoc);
const page = applyHtmlPageTemplate(
template,
{
bodyHtml: parts.bodyHtml,
headHtml: parts.featureHeadHtml,
title: 'Hello',
values: { date: '2026-10-28' },
},
{ templatePath: '_templates/post.html', outputPath: 'posts/hello.html' },
);
无名者 <slot> 接受身体(介于 <!-- squisq:content --> 标记,哪些 htmlToMarkdownDoc 在再导入时的荣誉,被命名的槽接收了文本值或保留了倒置子,相对的URL从模板的文件夹重置到页面,模板中的其他所有内容都会被复制为字节.
子路径也输出 markdownDocsToPlainHtmlBundle 编号 : markdownDocsToHtmlBundle (重复多功能ZIP捆绑 .md 链接重写为 .html, (中文(简体) ), htmlToMarkdownDocSync 编号 : htmlToMarkdown和助手(collectImagePaths, (中文(简体) ), collectLinkRefs, (中文(简体) ), inferMimeType) (中文(简体) ).
联布办事处
import { markdownDocToEpub } from '@bendyline/squisq-formats/epub';
// Export: MarkdownDocument → EPUB 3 (ArrayBuffer). No import path.
const epubBytes = await markdownDocToEpub(markdownDoc, {
title: 'My Book',
author: 'Jane Doe',
images, // Map<string, ArrayBuffer> — embedded when provided
coverImage, // optional JPEG/PNG
});
分会分出H1/H2边界. 提供 audio + 键 audioSegments 生成EPUB 3 Media Overlays(SMIL)用于同步解说.
PPTX 密码
import {
docToPptx,
markdownDocToPptx,
pptxToMarkdownDoc,
pptxToContainer,
} from '@bendyline/squisq-formats/pptx';
// Export: MarkdownDocument → PPTX (ArrayBuffer)
// slideBreak: 'h1' | 'h2' (default — H1 and H2 both break) | 'heading'
const pptxBytes = await markdownDocToPptx(markdownDoc, { slideBreak: 'h2', images });
// Export: player-ready Doc -> 16:9 PPTX using the slideshow's canonical
// block expansion and materialized visual layers (managed cover included by default)
const visualDeck = await docToPptx(slideshowDoc, { images });
// Import: PPTX → MarkdownDocument (add { extractImages: true } to reference slide images)
const imported = await pptxToMarkdownDoc(pptxBuffer);
// Import with assets: PPTX → ContentContainer (markdown + extracted slide images)
const container = await pptxToContainer(pptxBuffer);
忠诚: markdownDocToPptx 保留内线格式化为 DraigmL 运行. docToPptx 处理模板备份/玩家准备 Doc 作为可视化的甲板:它使用与幻灯片显示视图相同的可渲染区块平整,计时扩展,被管理-覆盖策略,主题,过渡,和可实现的地层堆栈,因此PPTX有相同的幻灯片计数和相匹配的16:9画布. 文本、形状、表格、路径和提供的图像成为可编辑的本地PowerPoint对象;只有浏览器的地图/视频/人造相片层在提供或标有标签的文本倒置时会降解为静态图像。 导入读取幻灯片顺序 ppt/presentation.xml ,并转换每张幻灯片的标题(~H2),正文(~正文列表)和表格. 幻灯片图像提取( v1.5) : 导入现在可以提取幻灯片级别 <p:pic> 位图进入 images/ —— 说 pptxToContainer 返回带有这些文件和力量的容器 extractImages: true时 pptxToMarkdownDoc 默认情况下离开它。 诚实限制: 只有幻灯片级别 <p:pic> 取出位图——布局/主图像、图表、智能艺术和图片填充 没有。 。 。 .
简历
import { csvToMarkdownDoc, markdownDocToCsv, parseCsv } from '@bendyline/squisq-formats/csv';
// Import: CSV (string | ArrayBuffer | Blob) → single-table MarkdownDocument
const tableDoc = await csvToMarkdownDoc(csvText, { delimiter: ',', hasHeader: true });
// Export: serializes one table node to CSV text (the first by default)
const csv = markdownDocToCsv(markdownDoc);
// Pick another table in a multi-table document:
const second = markdownDocToCsv(markdownDoc, { tableIndex: 1 });
自成一体的 RFC-4180 解析器/序列器(不是OOXML). 导出时单元格格式被平整为纯文本 。 导出一个表格——第一个,或 tableIndex (零基数). 远道而来 tableIndex 抛出; 无表格的文档导出为空字符串.
XLSX 密码
import { xlsxToMarkdownDoc, markdownDocToXlsx } from '@bendyline/squisq-formats/xlsx';
// Import: XLSX → MarkdownDocument (one table per sheet; or pick one via `sheet`)
const imported = await xlsxToMarkdownDoc(xlsxBuffer, { sheet: 0 });
// Export: MarkdownDocument → XLSX (ArrayBuffer) — one worksheet per markdown table
const xlsxBytes = await markdownDocToXlsx(markdownDoc);
导出执行(v1.5),只使用表格的忠诚度: 每一次减价 table 成为一个工作表,以最近的前一个标题命名(自动命名) Sheet1, (中文(简体) ), Sheet2,否则). 所有非表内容被删除. 数字外观的单元格被写成数字;其他的则被写成内线字符串. 没有表格的文档产生一个空的(但有效)工作表——导出从不丢出. markdownDocToXlsx 编号 : docToXlsx 现在返回 Promise<ArrayBuffer> (以前投掷/返回) Blob) (中文(简体) ).
集装箱 ZIP
import {
containerToZip,
zipToContainer,
ZipSafetyError,
} from '@bendyline/squisq-formats/container';
// ContentContainer → ZIP Blob (paths preserved)
const zipBlob = await containerToZip(container);
// ZIP → MemoryContentContainer (directories skipped, path traversal rejected)
const container2 = await zipToContainer(zipData, {
maxUncompressedBytes: 128 * 1024 * 1024,
});
归档导入安全
每次生产ZIP读作"容器ZIP/DBK嗅觉和OOXML后置DOCX",
PPTX 和 XLSX 导入“使用一个 JSZip 支持的限定读取会话 。 会议
在通货膨胀之前检查路径和中央目录元数据,然后消费
JSZip的增量成员流,同时分享实际排放的字节预算
包括所有成员。 重复的OOXML部分读取被缓存并充电一次;
并行的流都暂停在第一次失败上 . [Content_Types].xml
在DOM解析前,上限为 1 MiB,每个关系部分为 4 MiB.
OoxmlPackage 不透明 : 用 openPackage() 和通过
而不是进入一个原始的JSZip档案.
ZipSafetyLimits 由 zipToContainer 由OOXML继承
导入选项类型 :
| 外地 | 默认 | 含义 |
|---|---|---|
maxEntries | 10_000 | 中央记录共计,包括目录记录 |
maxEntryUncompressedBytes | maxUncompressedBytes | 为一名成员保留的最大排放字节数 |
maxUncompressedBytes | 512 * 1024 * 1024 | 整个归档中释放的总字节 |
maxCompressionRatio | 1_000 | 一名成员的最大未压缩/压缩比率 |
失败的是 ZipSafetyError 实例,从软件包根导出
页:1 /container 财务报告和审定财务报表 /ooxml 潜行道. 他们暴露了 code,并酌情
path, (中文(简体) ), limit, (中文(简体) ), actual,以及 cause。稳定代码是 invalid-limit, (中文(简体) ),
invalid-archive, (中文(简体) ), unsafe-path, (中文(简体) ), invalid-entry-metadata, (中文(简体) ),
too-many-entries, (中文(简体) ), entry-too-large, (中文(简体) ), archive-too-large, (中文(简体) ),
compression-ratio-exceeded, (中文(简体) ), size-mismatch, (中文(简体) ), crc-mismatch,以及
decompression-failed。 。 。 .
JSZip的公开暂停是合作性的:它阻止了下一次压缩输入 勾选,但 pako 可能已完成在当前同步状态下已经生成块 勾选。 一旦限值失败,斯奎斯克立即丢弃这些块...” 保留、计算或写入容器.
Doc- 级别召集函数
每种格式也出口 Doc- 处理 Markdown 文档内部转换的关卡:
import { docToDocx, docxToDoc } from '@bendyline/squisq-formats/docx';
import { docToPdf, pdfToDoc } from '@bendyline/squisq-formats/pdf';
import { docToPptx, pptxToDoc } from '@bendyline/squisq-formats/pptx';
import { docToEpub } from '@bendyline/squisq-formats/epub';
import { csvToDoc } from '@bendyline/squisq-formats/csv';
import { xlsxToDoc, docToXlsx } from '@bendyline/squisq-formats/xlsx';
程序化 convert()
@bendyline/squisq-formats/registry (也从包根再出)是一个统一,格式不可知的前门,覆盖每个转换器. 每个格式都是 FormatDefinition 能够将原始字节导入到 MarkdownDocument 转轴和/或再出口; convert() 将任何源常态化为 a Doc,可选择性地应用主题/变换,然后向目标出口商交接。 每个结果都一样 ConversionResult (单位:千美元)bytes + 键 mimeType + 键 suggestedFilename + 键 warnings) (中文(简体) ). 转换器模块可以懒散地装入,因此导入注册时从来不急于捆绑一个重的转换器.
import { convert } from '@bendyline/squisq-formats/registry';
const result = await convert(
{ kind: 'markdown', markdown: '# Hello', baseName: 'greeting' },
'docx',
);
// result.bytes, result.mimeType, result.suggestedFilename === 'greeting.docx'
ConvertOptions 还接受 themeRegistry 财务报告和审定财务报表 transformRegistry 页:1
用户自定义. transformStyle 可以是样式 id 或
呼叫范围 TransformStyleConfig; 这些选项永远不会改变进程- 全球
状态.
来源是 { kind: 'bytes' | 'markdown' | 'doc', … }; 字节来源是被魔法字节+扩展(通过)所闻的格式 from 跳过). 失败投出结构化 ConversionError 拥有稳定 code (单位:千美元)unknown-format, (中文(简体) ), unsupported-input, (中文(简体) ), unsupported-output, (中文(简体) ), invalid-input, (中文(简体) ), missing-dependency, (中文(简体) ), conversion-failed加上一个 hint。 。 。 .
玩家嵌入的 HTML 导出( E)html 编号 : htmlzip(中文(简体) ) 需要独立的玩家捆绑。 过 resolvePlayerScript,否则你会得到一个 missing-dependency 错误 :
const html = await convert({ kind: 'markdown', markdown: src }, 'html', {
resolvePlayerScript: () =>
import('@bendyline/squisq-react/standalone-source').then((m) => m.PLAYER_BUNDLE),
});
也导出 : createRegistry 编号 : defaultRegistry 编号 : defaultFormats, (中文(简体) ), BUILTIN_FORMAT_IDS, (中文(简体) ), ConversionError,则 ConvertSource 编号 : ConvertOptions 编号 : ConversionResult 编号 : FormatDefinition 编号 : FormatRegistry 类型.
子路径导出
| 子路径 | 目录 |
|---|---|
@bendyline/squisq-formats/docx | DOCX 进出口(+) docxToContainer(中文(简体) ) |
@bendyline/squisq-formats/pdf | PDF 进出口(+) pdfToContainer, (中文(简体) ), configurePdfWorker(中文(简体) ) |
@bendyline/squisq-formats/html | 玩家 HTML 导出, 静态 Plain- HTML 导出 + 捆绑, HTML 导入 |
@bendyline/squisq-formats/html-prepare | prepareMarkdownDocForPlainHtml: plain-HTML 页面的数据表和图片 |
@bendyline/squisq-formats/html-icons | plainHtmlIcons: 内置图标作为平版 HTML 页面的 SVG 大纲 |
@bendyline/squisq-formats/epub | EPUB 3 电子图书导出(带有可选的媒体重叠) |
@bendyline/squisq-formats/pptx | PPTX 导出 + 导入( 文本/ 列表/ 表格 + 幻灯片图像) |
@bendyline/squisq-formats/xlsx | XLSX 导入 + 只用表格导出 |
@bendyline/squisq-formats/csv | CSV进出口(RFC 4180) |
@bendyline/squisq-formats/ooxml | 共享OOXML基础设施(包装读取器/写作机、XML公用事业、命名空间) |
@bendyline/squisq-formats/diagrams | rasterizeDiagrams 编号 : findDiagrams: 图表作为文档导出图片 |
@bendyline/squisq-formats/container | ContentContainer ZIP序列化 |
@bendyline/squisq-formats/registry | 登记册格式+程序 convert() (也从根上再出) |
包根再导出普通转换器; ./container,平面-HTML/bundle函数, docxToContainer, (中文(简体) ), pdfToContainer, (中文(简体) ), PdfPageSize,图像公用设施只能是子路径.
见全 API 参考 每个签名和选项接口.
相关软件包
| 软件包 | 说明 |
|---|---|
| @bendyline/squisq (英语) | 无头核心——计划,模板,空间,标记下,存储 |
| @bendyline/squisq-反应 | 渲染道克的反射组件( +) PLAYER_BUNDLE(中文(简体) ) |
| @bendyline/squisq-cli (英语) | squisq CLI — 批量转换 + MP4 渲染 |
| @bendyline/squisq-editor-反应 | 使用原始/ WYSIWYG/ 预览模式进行反应编辑器 |