npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

manifest-label-print

v0.1.7

Published

Label print engine (browser & CLodop), template mapper and CLodop setup utilities for manifest-design

Readme

manifest-label-print

manifest-design 的标签打印引擎 — 提供模板标准化、浏览器截图打印与 CLodop 打印能力,可与 manifest-label-designer 配套使用。

目录


安装

npm install manifest-label-print

若需可视化设计器,请同时安装 manifest-label-designer:

npm install manifest-label-designer manifest-label-print

与 manifest-label-designer 联用

两个包的分工如下:

| 包 | 职责 | |----|------| | manifest-label-designer | 可视化标签设计器 UI,产出 { components, canvasConfig } 模板 JSON | | manifest-label-print(本包) | 将模板 JSON 转为打印任务,执行浏览器或 CLodop 打印 |

典型流程:

设计器编辑模板 → 导出/读取 JSON → toPrintTemplate() → executePrint()

设计器内部已依赖本包完成打印;若你不使用设计器 UI,只需本包 + 自建的标签预览 DOM 即可完成打印集成。


快速开始

import { toPrintTemplate, executePrint } from 'manifest-label-print'

const designJson = {
  components: [
    {
      id: 'text-1',
      type: 'text',
      x: 5,
      y: 8,
      width: 50,
      height: 10,
      content: '商品名称:示例',
      fontSize: 14,
      color: '#333'
    }
  ],
  canvasConfig: { width: 60, height: 40, unit: 'mm' }
}

const template = toPrintTemplate(designJson)
const target = document.querySelector('.preview-canvas') as HTMLElement | null

const result = await executePrint(template, {
  engine: 'browser',
  target
})

if (!result.success) {
  console.error(result.message)
}

使用前准备

浏览器打印

无需额外依赖。页面上需有一个与标签尺寸一致的预览 DOM,作为截图目标传入 options.target。

CLodop 打印

  1. 在本机安装并启动 CLodop 打印服务(默认端口 8000 / 18000)
  2. 将官方 LodopFuncs.js 放到业务项目静态资源目录,例如 public/LodopFuncs.js
  3. 打印前调用 ensureClodopReady({ scriptUrl: '/LodopFuncs.js' })

说明:本包不包含 LodopFuncs.js 文件,也不包含可视化设计器 UI。设计器场景见 manifest-label-designer(内置 helper 脚本)。


使用方式

浏览器截图打印

适合快速集成、无 CLodop 环境时使用。对预览 DOM 截图后调用系统打印对话框。

import { toPrintTemplate, executePrint } from 'manifest-label-print'

const template = toPrintTemplate(designJson)
const target = document.querySelector('.preview-canvas') as HTMLElement | null

const result = await executePrint(template, {
  engine: 'browser',
  target,
  copies: 1 // 可选,默认 1
})

要点

  • target 必填
  • 固定为截图打印,无 mode 选项
  • 截图时会自动忽略 .grid-background、.selection-handles 等设计器辅助元素(若 DOM 中存在)

CLodop 原生模式打印

适合标签机场景。按组件 JSON 下发 CLodop 指令,打印精度高、速度快。

import {
  toPrintTemplate,
  executePrint,
  ensureClodopReady,
  formatClodopDiagnostics
} from 'manifest-label-print'

const diagnostics = await ensureClodopReady({ scriptUrl: '/LodopFuncs.js' })
if (!diagnostics.ready) {
  alert(formatClodopDiagnostics(diagnostics))
  throw new Error(diagnostics.message)
}

const template = toPrintTemplate(designJson)
const result = await executePrint(template, {
  engine: 'clodop',
  mode: 'native',
  preview: true // true=预览,false=直接打印
})

原生模式支持的组件类型

| 类型 | 说明 | |------|------| | text | 文本,支持字号、字体、颜色、加粗、对齐 | | barcode | 条形码,format 如 Code128 会自动映射为 128Auto | | qrcode | 二维码,支持 errorCorrectionLevel | | horizontal-line / vertical-line | 横线 / 竖线 | | rectangle | 矩形边框 | | image | 图片,需有非空 src |

原生模式不支持时会自动降级

以下情况会降级为截图模式(此时 target 必填):

  • 组件类型为 table、input、date、price、circle 等
  • 组件 rotation !== 0 或 opacity !== 1
  • 组件 visible === false

CLodop 截图模式打印

适合复杂布局或原生模式无法渲染的模板。对 DOM 截图后通过 CLodop 打印图片。

import {
  toPrintTemplate,
  executePrint,
  ensureClodopReady,
  formatClodopDiagnostics
} from 'manifest-label-print'

const diagnostics = await ensureClodopReady({ scriptUrl: '/LodopFuncs.js' })
if (!diagnostics.ready) {
  throw new Error(formatClodopDiagnostics(diagnostics))
}

const template = toPrintTemplate(designJson)
const target = document.querySelector('.preview-canvas') as HTMLElement | null

const result = await executePrint(template, {
  engine: 'clodop',
  mode: 'image',
  target,
  preview: true,
  printerName: '标签打印机' // 可选,指定 CLodop 打印机名称
})

要点

  • target 必填
  • mode 默认为 'image'

Vue 3 组件内集成

<script setup lang="ts">
import { ref } from 'vue'
import {
  toPrintTemplate,
  executePrint,
  ensureClodopReady,
  formatClodopDiagnostics,
  type PrintEngine,
  type PrintMode
} from 'manifest-label-print'

const props = defineProps<{
  designJson: { components: unknown[]; canvasConfig: Record<string, unknown> }
}>()

const canvasRef = ref<HTMLElement | null>(null)
const engine = ref<PrintEngine>('browser')
const mode = ref<PrintMode>('native')

const handlePrint = async () => {
  if (engine.value === 'clodop') {
    const diagnostics = await ensureClodopReady({ scriptUrl: '/LodopFuncs.js' })
    if (!diagnostics.ready) {
      window.alert(formatClodopDiagnostics(diagnostics))
      return
    }
  }

  const template = toPrintTemplate(props.designJson)
  const result = await executePrint(template, {
    engine: engine.value,
    mode: mode.value,
    target: canvasRef.value,
    preview: engine.value === 'clodop'
  })

  if (!result.success) {
    window.alert(result.message || '打印失败')
  }
}
</script>

<template>
  <div ref="canvasRef" class="preview-canvas">
    <!-- 根据 designJson 渲染标签内容 -->
  </div>
  <button type="button" @click="handlePrint">打印</button>
</template>

兼容旧版模板数据

toPrintTemplate / normalizeTemplateInput 支持多种输入格式:

import { normalizeTemplateInput, toPrintTemplate } from 'manifest-label-print'

// 标准格式
toPrintTemplate({
  components: [],
  canvasConfig: { width: 60, height: 40, unit: 'mm' }
})

// 旧版 { data } 字段
toPrintTemplate({
  data: components,
  canvasConfig: { width: 60, height: 40, unit: 'mm' }
})

// 仅组件数组(使用默认 60×40mm 画布)
toPrintTemplate(components)

// 仅标准化,不包装 schemaVersion
normalizeTemplateInput(designJson)

标准化后的 PrintTemplate 结构:

interface PrintTemplate {
  schemaVersion: '1.0'
  source: 'manifest-design'
  components: PrintComponent[]
  canvasConfig: PrintCanvasConfig
}

默认画布配置(缺省时):

| 字段 | 默认值 | |------|--------| | width | 60 | | height | 40 | | unit | 'mm' | | zoom | 1 | | showGrid | true | | showRuler | true | | showGuides | true |


适配器与偏好存储

import {
  BrowserPrintAdapter,
  ClodopPrintAdapter,
  executePrint,
  getPreferredPrintEngine,
  setPreferredPrintEngine,
  getPreferredPrintMode,
  setPreferredPrintMode,
  isClodopRuntimeReady
} from 'manifest-label-print'

setPreferredPrintEngine('clodop')
setPreferredPrintMode('native')

if (getPreferredPrintEngine() === 'clodop' && !isClodopRuntimeReady()) {
  await ensureClodopReady({ scriptUrl: '/LodopFuncs.js' })
}

const adapters = [new BrowserPrintAdapter(), new ClodopPrintAdapter()]
await executePrint(template, {
  engine: getPreferredPrintEngine(),
  mode: getPreferredPrintMode(),
  target: previewElement
}, adapters)

偏好写入 localStorage,并自动迁移旧键名:print_engine、label_print_engine、print_mode、label_print_mode。

| 存储键 | 说明 | |--------|------| | manifest-print-engine | 当前首选引擎 | | manifest-print-mode | 当前首选 CLodop 模式 |


API 参考

模板转换

| 方法 | 说明 | |------|------| | toPrintTemplate(input) | 转为带 schemaVersion: '1.0' 的打印模板 | | normalizeTemplateInput(input) | 标准化为 { components, canvasConfig } |

打印入口

| 方法 / 类 | 说明 | |-----------|------| | executePrint(template, options, adapters?) | 统一打印入口 | | resolvePrintAdapter(engine, adapters?, fallbackToBrowser?) | 解析可用打印引擎 | | getDefaultPrintAdapters() | 获取默认适配器列表 | | BrowserPrintAdapter | 浏览器截图打印适配器 | | ClodopPrintAdapter | CLodop 打印适配器 |

PrintJobOptions 字段

| 字段 | 类型 | 默认值 | 说明 | |------|------|--------|------| | engine | 'browser' \| 'clodop' | — | 打印引擎(必填) | | mode | 'image' \| 'native' | 'image' | CLodop 打印模式 | | target | HTMLElement \| null | — | 截图目标 DOM | | preview | boolean | — | CLodop 是否预览(PREVIEW / PRINT) | | copies | number | 1 | 打印份数(浏览器引擎有效) | | printerName | string | — | CLodop 打印机名称 | | fallbackToBrowser | boolean | 见说明 | 引擎不可用时是否回退浏览器 |

PrintJobResult 字段

| 字段 | 类型 | 说明 | |------|------|------| | success | boolean | 是否成功 | | message | string | 结果描述(含降级提示) | | error | unknown | 异常对象 |

CLodop 环境工具

| 方法 | 说明 | |------|------| | ensureClodopReady(options?) | 注入 helper 脚本并等待 CLodop 就绪,返回诊断信息 | | ensureClodopHelperLoaded(options?) | 同上,返回 boolean | | isClodopRuntimeReady() | 同步检测 CLodopJsState === 'complete' 且实例可用 | | formatClodopDiagnostics(diagnostics) | 格式化诊断信息为可读字符串 |

ClodopSetupOptions 字段

| 字段 | 类型 | 默认值 | 说明 | |------|------|--------|------| | scriptUrl | string | — | LodopFuncs.js 地址,如 '/LodopFuncs.js' | | timeoutMs | number | 8000 | 等待超时(毫秒) | | scriptId | string | 'manifest-clodop-helper' | 注入的 <script> 标签 id |

ClodopDiagnosticCode 枚举

| 值 | 含义 | |----|------| | ready | 已就绪 | | helper_script_load_failed | helper 脚本加载失败 | | helper_not_injected | helper 未注入(未传 scriptUrl) | | helper_loading_timeout | 加载超时或服务不可达 | | clodop_instance_unavailable | 脚本已加载但无可用实例 |

偏好存储

| 方法 | 说明 | |------|------| | getPreferredPrintEngine() | 读取首选引擎,默认 'browser' | | setPreferredPrintEngine(engine) | 写入首选引擎 | | getPreferredPrintMode() | 读取首选 CLodop 模式,默认 'image' | | setPreferredPrintMode(mode) | 写入首选 CLodop 模式 | | getStoredPrintEngine() | 读取存储值,无则 null | | getStoredPrintMode() | 读取存储值,无则 null |

类型定义

本包导出以下 TypeScript 类型:

export type {
  DesignTemplateSnapshot,
  PrintAdapter,
  PrintCanvasConfig,
  PrintComponent,
  PrintEngine,
  PrintMode,
  PrintJobOptions,
  PrintJobResult,
  PrintTemplate
} from 'manifest-label-print'

export type {
  ClodopDiagnosticCode,
  ClodopDiagnostics,
  ClodopSetupOptions
} from 'manifest-label-print'

行为说明

  • 浏览器引擎固定为截图打印,必须提供 options.target
  • CLodop native 模式在不支持时会自动降级为 image 模式(message 会提示 Native mode fallback to image mode)
  • 坐标与尺寸单位为毫米(mm),CLodop 内部转换为 0.1mm
  • 截图使用 html2canvas,默认 scale: 2,背景色 #ffffff
  • 设计器 UI 不在本包范围内,请配合 manifest-label-designer 或自建渲染层

完整示例

从设计器 JSON 到 CLodop 原生打印

import {
  toPrintTemplate,
  executePrint,
  ensureClodopReady,
  formatClodopDiagnostics
} from 'manifest-label-print'

// 通常来自 manifest-label-designer 导出的 JSON
const exportedJson = {
  components: [
    { id: 't1', type: 'text', x: 5, y: 5, width: 50, height: 8, content: '示例商品', fontSize: 14, fontWeight: 'bold' },
    { id: 'b1', type: 'barcode', x: 8, y: 20, width: 44, height: 10, content: '123456789012', format: 'Code128' }
  ],
  canvasConfig: { width: 60, height: 40, unit: 'mm', zoom: 1, showGrid: true, showRuler: true, showGuides: true }
}

const diagnostics = await ensureClodopReady({ scriptUrl: '/LodopFuncs.js' })
if (!diagnostics.ready) {
  throw new Error(formatClodopDiagnostics(diagnostics))
}

const template = toPrintTemplate(exportedJson)
const result = await executePrint(template, {
  engine: 'clodop',
  mode: 'native',
  preview: true
})

console.log(result.message) // "Printed with CLodop native mode"

含表格模板(自动降级截图)

const template = toPrintTemplate({
  components: [
    { id: 'tbl', type: 'table', x: 2, y: 2, width: 56, height: 36 /* ... */ }
  ],
  canvasConfig: { width: 60, height: 40, unit: 'mm' }
})

// table 不支持 native,需提供 target
const result = await executePrint(template, {
  engine: 'clodop',
  mode: 'native',
  target: document.querySelector('.preview-canvas'),
  preview: true
})
// result.message === 'Native mode fallback to image mode'

常见问题

CLodop 无法打印

  1. 确认本机 CLodop 服务已启动(localhost:8000 或 localhost:18000)
  2. 确认 LodopFuncs.js 路径正确,且打印前已调用 ensureClodopReady({ scriptUrl: '...' })
  3. 使用 formatClodopDiagnostics(diagnostics) 查看详细诊断

浏览器打印空白

  • 确认 target 元素已渲染且尺寸与 canvasConfig 一致
  • 跨域图片可能导致截图失败,需配置 CORS 或使用同源资源

原生模式意外变成截图

  • 检查模板是否含 table、date、price、input、circle 等类型
  • 检查组件是否有旋转(rotation !== 0)或透明度(opacity !== 1)

只想用设计器,还要装本包吗?

manifest-label-designer 将本包列为 peerDependency,宿主项目需同时安装。


完整集成示例

本仓库提供可运行的最小集成示例,演示设计器 + 打印引擎的完整接入:

源码:examples/verify-npm-package

git clone https://github.com/ymf-930/manifest-design.git
cd manifest-design

# 先构建两个 npm 包
npm run build:print-package
npm run build --prefix packages/manifest-label-designer

cd examples/verify-npm-package
npm install
npm run dev

示例 main.ts 核心配置:

import { createPinia } from 'pinia'
import Antd from 'ant-design-vue'
import 'ant-design-vue/dist/reset.css'
import 'manifest-label-designer/style.css'

app.use(createPinia())
app.use(Antd)

若仅使用本包(不用设计器 UI),可参考上文 Vue 3 组件内集成,并将 public/LodopFuncs.js 用于 CLodop 联调(示例目录已包含该文件)。


开发与发布

# 在 monorepo 根目录
npm run build:print-package

# 在 packages/manifest-label-print
npm version patch
npm publish --access public --registry https://registry.npmjs.org/

License

MIT