@atjson/renderer-hir

中文文档
0.27.0发布于 2026/08/10Apache-2.0TypeScriptESM + CJS构建来源已验证近 30 天下载 1.7万

Generalized tools for generating documents in a hierarchical fashion

原始使用文档

🌳 @atjson/renderer-hir

This renderer is designed to render out to hierarchical formats like HTML, markdown, and the DOM.

Renderers use generators to return the content around annotations so each annotation has contextual awareness of what's going on. Render functions are keyed on their annotation type (or the classified type). In addition, there are 3 special functions that can be overridden:

  • *renderAnnotation, which will be called for every annotation (even unknown annotations)
  • *root, which is the root node of the document being rendered. Overriding this allows for output to be fixed accordingly (for example, joining the yielded contents when the string output is expected to be a string)
  • text, which will be called for all text nodes.

🖍 Writing a Renderer

Let's write a renderer for Slack! Slack has a simple message format that looks somewhat like markdown (but isn't). We'll use their documentation found here to write this renderer.

First, install the package:

npm install --save @atjson/renderer-hir

And import it to the top of the file:

import Renderer from "@atjson/renderer-hir";

export default class SlackRenderer extends Renderer {}

We have a renderer that will return the text of the document we pass in! (yay!)

Let's make the renderer return a string instead of an array of strings:

import Renderer from "@atjson/renderer-hir";

export default class SlackRenderer extends Renderer {
  *root() {
    let text = yield;
    return text.join("");
  }
}

Let's start writing tests to verify what we're writing works. For this example we'll be using 🃏Jest as our testing framework.

We're going to use the OffsetSource as our source document and set of annotations, since it's provided with out-of-the-box support for the basic syntax that Slack supports.

import OffsetSource from "@atjson/offset-annotations";
import SlackRenderer from "../src";

describe("SlackRenderer", () => {
  test("it returns text", () => {
    let doc = new OffsetSource({
      content: "Hello!",
      annotations: [],
    });

    expect(SlackRenderer.render(doc)).toBe("Hello!");
  });
});

Let's add some test cases for this, from their docs:

import OffsetSource, { Bold, Italic, Strikethrough } from '@atjson/offset-annotations';
import SlackRenderer from '../src';

describe('SlackRenderer', () => {
  test('it returns text', () => { ... });

  test('bold', () => {
    let doc = new OffsetSource({
      content: 'To bold, surround your text with asterisks: your text',
      annotations: [new Bold({ start: 44, end: 53 })]
    });

    expect(SlackRenderer.render(doc)).toBe('To bold, surround your text with asterisks: *your text*');
  });

  test('italic', () => {
    let doc = new OffsetSource({
      content: 'To italicize, surround your text with underscores: your text',
      annotations: [new Italic({ start: 51, end: 60 })]
    });

    expect(SlackRenderer.render(doc)).toBe('To italicize, surround your text with underscores: _your text_');
  });

  test('strikethrough', () => {
    let doc = new OffsetSource({
      content: 'To strikethrough, surround your text with tildes: your text',
      annotations: [new Italic({ start: 50, end: 59 })]
    });

    expect(SlackRenderer.render(doc)).toBe('To strikethrough, surround your text with tildes: ~your text~');
  });
});

Running tests should result in 3 failing tests.

Now that we have some failing test cases, let's go back to our renderer and implement bold markup:

import Renderer from "@atjson/renderer-hir";

export default class SlackRenderer extends Renderer {
  *Bold() {
    let text = yield;
    return `*${text.join("")}*`;
  }

  *root() {
    let text = yield;
    return text.join("");
  }
}

We use Bold here as a convention to match the class name of the annotation. Alternatively, we can use the key bold to generate the markup (it's up to you how you want to write it 😉).

Running tests now should result in 2 failing tests. 🎉

Now that we've got the hang of the first one, let's bang out the other 2 failing tests:

import Renderer from "@atjson/renderer-hir";

export default class SlackRenderer extends Renderer {
  *Bold() {
    let text = yield;
    return `*${text.join("")}*`;
  }

  *Italic() {
    let text = yield;
    return `_${text.join("")}_`;
  }

  *Strikethrough() {
    let text = yield;
    return `~${text.join("")}~`;
  }

  *root() {
    let text = yield;
    return text.join("");
  }
}

版本与发布记录

@atjson/renderer-hir 共发布 112 个版本,首次发布于 2017/10/05;过去 12 个月发布了 1 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.27.0latest2026/08/102 个月前
0.26.42025/08/281.2 年前
0.26.4-gdocs-paste-extensions.12gdocs-paste-extensions2025/02/081.7 年前
0.26.32024/11/212 年前
0.26.22024/04/302 年前
0.26.12024/04/012 年前

其他发布通道:dev → 0.22.13-dev.0,gdocs-paste-extensions → 0.26.4-gdocs-paste-extensions.12。

关于 @atjson/renderer-hir 的常见问题

@atjson/renderer-hir 是什么?

Generalized tools for generating documents in a hierarchical fashion

如何安装 @atjson/renderer-hir?

在项目目录运行 npm install @atjson/renderer-hir,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:@atjson/document(>= 0.29.0 < 1)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@atjson/renderer-hir 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@atjson/renderer-hir 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@atjson/renderer-hir 可以商用吗?

@atjson/renderer-hir 使用 Apache-2.0 许可。宽松许可:允许商业使用、修改和再分发,并附带明确的专利授权;分发时需保留许可与 NOTICE 文件,修改过的文件要注明改动。以上为概括,不构成法律意见,请以许可原文为准。

@atjson/renderer-hir 的下载量有多少?

根据 npm 官方下载统计,@atjson/renderer-hir 在 2026/10/07 – 2026/11/05 这 30 天内被下载 16,915 次,日均约 564 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@atjson/renderer-hir 还在维护吗?

最新版本 0.27.0 发布于 2026/08/10(2 个月前);至今共发布 112 个版本,其中过去 12 个月发布了 1 个;首次发布于 2017/10/05。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。