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

inact

v0.0.3

Published

Transpile the JSX to HTML strings.

Readme

inact

Inact 是一个可以将 JSX 直接输出为 HTML 字符串的转换库。

使用其他语言阅读:English | 中文

function Paragraph(): string {
  return <p>hello world</p>;
}

console.log(<Paragraph />); // -> '<p>hello world</p>'

介绍

这个项目可以用来做什么?

众所周知,在不使用第三方库或框架的前提下,大部分开发人员,都会选择使用模板字符串来编写页面元素。

例如下列代码,这是一个最简单的示例:

const content = 'hello world';
const app = document.getElementById('app');

app.innerHTML = `
  <p>${content}</p>
`;

除此之外,我们也可以使用函数来创建页面元素:

const text = 'hello world';
const app = document.getElementById('app');
const element = document.createElement('p');
const content = document.createTextNode(text);

element.appendChild(content);
app.insertBefore(element, null);

但相较于前者,它太过于复杂了,如果涉及的页面元素较多,代码也会变得没有可读性。因此,人们更加倾向于使用模板字符串。

可是,在使用模板字符串来编写 HTML 时,IDE 并不会有标签高亮和补全提示,代码写错时也不会有对应的报错提示。要是涉及到模板的 for 循环遍历输出...如果你写过 ASP、JSP、PHP,一定知道这玩意有多恶心。~~(IDEA:没想到吧,我还真有模板字符串的标签高亮和补全。)~~

那...有没有一种可能,我们可以使用 JSX 来解决这个问题?

function Paragraph(props: { content: string }): string {
  return <p>{props.content}</p>;
}

尽管现如今,出现了像 ReactPreact 之类的优秀项目,但它们都太「重」了。如果我们只是想简单地去编写一些页面结构,那可能没有多少人,仅仅是为了使用 JSX 就将项目依赖于第三方库的生态体系。

不是所有人都有虚拟 DOM 的需求场景,也不是所有人都想在自己的小型项目中编写 apprender

那么,Inact 是怎么做的?

const content = 'hello world';
const app = document.getElementById('app');

app.innerHTML = <p>{content}</p>;

~~Wow, amazing, only JSX can do!~~

( •̀ ω •́ )✧ 不做任何复杂的处理,纯粹地输出 HTML 原生字符串,剩下的逻辑,全都由你亲手处理。

安装

我推荐将 Inact 直接搭配 TypeScript 来使用,你可以使用 npm,或者其它包管理器安装相关依赖。

npm install -D typescript inact

当然,如果你不使用 TypeScript 开发,也可以集成 ESBuildRollup 等工具,Inact 本质上是一个 jsx-runtime,可以自由搭配使用。

使用

以 TypeScript 为例,当安装好相关依赖后,我们需要先在项目根目录执行 tsc --init 命令,并修改生成的 tsconfig.json 文件内容:

{
  "compilerOptions": {
    "jsx": "react-jsx",
    "jsxImportSource": "inact"
  }
}

这就完了?没错,修改 jsxjsxImportSource 后,你便可以直接使用 TSX 来编写你的页面代码了。

function Paragraph(props: { content: string }): string {
  return <p>{props.content}</p>;
}

const text: string = 'hello world';
const app: HTMLElement = document.getElementById('app')!;

app.innerHTML = <Paragraph content={text} />;

特性

class

支持数组和对象:

<div class={['foo', 'bar']} />
<div class={{ foo: true, bar: false }} />

style

支持小驼峰对象:

<div style={{ backgroundColor: 'red' }} />

children

字符串和数字会作为文本输出,nullundefinedtruefalse[] 不输出内容。数组会递归输出,所以 {[0, 1, 2]} 会输出 012。像 {{}} 这样的普通对象不是合法的 children。

boolean attribute

布尔属性通过是否存在来表示状态,<button disabled /><button disabled={true} /> 会输出 <button disabled></button>disabled={false} 会省略该属性。

这与 MDNWHATWG HTML 对 boolean attribute 的说明一致:存在表示 true,不存在表示 false。

Fragment

可以使用 <>...</> 或者 <Fragment>...</Fragment> 来对元素进行分组,从而无需在 HTML 中添加额外的包裹节点,提升代码可读性和维护性。

dangerouslySetInnerHTML

如果你需要渲染原始 HTML 文本:

<div dangerouslySetInnerHTML={{ __html: '<span>Raw HTML</span>' }} />

关于

最初,我是因为要在 Docsify 中开发插件(这是一个可以将 Markdown 转换为 HTML 并渲染至页面的文档框架),便使用了模板字符串来处理页面元素,docsify 的大部分插件也都是这么做的。

但随着时间的推移,我愈发感到代码变得难以维护和阅读,所以开始使用 vhtml 来重构插件,该项目也是 Preact 曾经推荐用于纯 HTML 字符串输出的解决方案。

可是 vhtml 并没有完全解决我的使用需求,例如,我要为 class 传入数组亦或是对象,它并没有为其提供支持。其次是 vhtml 仅仅提供了 h 函数,如果想在 TypeScript 中使用,还需要额外的配置并自行定义 JSX 类型和编写 Fragment 函数,不能做到开箱即用。

更重要的是,在 vhtml 的源码中,使用到了 arguments 这个不被推荐、在严格模式中表现不一致的关键字。例如我现在习惯使用 bun 开发项目,就遇到了各种诡异的问题,它并不适合集成到现代代码中。

当然,这并不全是 vhtml 的问题,它是一个十分优秀的开源项目,只是不满足我的使用需求。在几乎搜遍全网,也没有找到类似的解决方案后,我便开发了这个项目。