# content-tag

> A rust program that uses a fork of swc to parse and transform Javascript containing the content-tag proposal

Latest version **4.2.0** (published 2026-05-08) · MIT license · 0 weekly downloads

## Install

```sh
npm install content-tag
pnpm add content-tag
yarn add content-tag
bun add content-tag
```

## Health

**Score 65/100 (B)** — status: active.

Positive: has types; esm support; no vulnerabilities; has provenance; high quality score.

Warnings: low downloads.

## Facts

| | |
|---|---|
| Version | 4.2.0 |
| Published | 2026-05-08 |
| First published | 2023-07-06 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | bundled |
| Module format | ESM |
| Dependencies | 0 |
| Unpacked size | 3.6 MB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| Provenance | attested (GitHub Actions) |
| GitHub stars | 12 |
| Maintainers | real_ate, ef4 |

## Links

- npm: https://www.npmjs.com/package/content-tag
- Repository: https://github.com/embroider-build/content-tag
- Homepage: https://github.com/embroider-build/content-tag#readme
- Issues: https://github.com/embroider-build/content-tag/issues
- npm.io page: https://npm.io/package/content-tag

## Recent versions

- 4.2.0 (latest) — 2026-05-08
- 4.1.1 — 2026-03-17
- 4.1.0 — 2025-12-23
- 4.0.0 — 2025-05-07
- 3.1.3 — 2025-05-01
- 3.1.2 — 2025-03-20
- 3.1.1 — 2025-02-01
- 3.1.0 — 2024-12-17
- 3.0.0 — 2024-11-10
- 2.0.3 — 2024-11-05
- 2.0.2 — 2024-09-21
- 2.0.1 — 2024-02-01
- 2.0.0 — 2024-02-01
- 1.2.2 — 2023-12-18
- 1.2.1 — 2023-12-13
- … 7 more at https://npm.io/package/content-tag/versions

## README

# content-tag

`content-tag` is a preprocessor for JS files that are using the content-tag proposal. This originated with Ember.js' GJS and GTS functionality. You can read more by [checking out the original RFC](https://rfcs.emberjs.com/id/0931-template-compiler-api/)

This preprocessor can be used to transform files using the `content-tag` spec to standard JS. It is built on top of [swc](https://swc.rs/) using Rust and is deployed as a wasm package.

## Installation

```sh
npm install content-tag
```

## Usage

### Node (CommonJS)

```js
let { Preprocessor } = require("content-tag");
let p = new Preprocessor();
let output = p.process("<template>Hi</template>");

console.log(output);
```

### Node (ESM)

```js
import { Preprocessor } from "content-tag";
let p = new Preprocessor();
let output = p.process("<template>Hi</template>");

console.log(output);
```

### Browser (ESM)

```js
import { Preprocessor } from "content-tag";
let p = new Preprocessor();
let output = p.process("<template>Hi</template>");

console.log(output);
```

## API

### `Preprocessor`

All `content-tag` public API lives on the `Preprocessor` object.

### `Preprocessor.process(src: string, options?: PreprocessorOptions): { code: string, map: string };`

Parses a given source code string using the `content-tag` spec into standard
JavaScript.

```ts
import { Preprocessor } from "content-tag";
let p = new Preprocessor();
let output = p.process("<template>Hi</template>");
```

### `Preprocessor.parse(src: string, options?: PreprocessorOptions): Parsed[];`

Parses a given source code string using the `content-tag` spec into an array of
`Parsed` content tag objects.

```ts
import { Preprocessor } from "content-tag";
let p = new Preprocessor();
let output = p.parse("<template>Hi</template>");
```

#### `PreprocessorOptions`

```ts
interface PreprocessorOptions {
  /** Default is `false` */
  inline_source_map?: boolean;

  filename?: string;
}
```

#### `Parsed`

````ts
interface Range {
  // Range in raw bytes.
  startByte: number;
  endByte: number;

  // Range in unicode codepoints.
  // CAUTION: see "Unicode Codepoint Slicing Warning" below.
  startChar: number;
  endChar: number;

  // utf16 is used by JavaScript strings.
  // e.g. str.slice(range.startUtf16Codepoint, range.endUtf16Codepoint)
  startUtf16Codepoint: number;
  endUtf16Codepoint: number;
}

interface Parsed {
  /**
   * The type for the content tag.
   *
   * 'expression' corresponds to a tag in an expression position, e.g.
   * ```
   * const HiComponent = <template>Hi</template>;
   * ```
   *
   * 'class-member' corresponds to a tag in a class-member position, e.g.
   * ```
   * export default class HiComponent extends Component {
   *   <template>Hi</template>
   * }
   * ```
   */
  type: "expression" | "class-member";

  /**
   * Currently, only template tags are parsed.
   */
  tagName: "template";

  /** Raw template contents. */
  contents: string;

  /**
   * Range of the contents, inclusive of the
   * `<template></template>` tags.
   */
  range: Range;

  /**
   * Range of the template contents, not inclusive of the
   * `<template></template>` tags.
   */
  contentRange: {
    start: number;
    end: number;
  };

  /**
   * Range of the opening `<template>` tag.
   */
  startRange: Range;

  /**
   * Range of the closing `</template>` tag.
   */
  endRange: Range;
}
````

## Unicode Codepoint Slicing Warning

If you have a string and want to use the range provided by our `parse` method to slice out parts of that string, you need avoid two major pitfalls.

First, you want to use our `startChar` and `endChar` not `startByte` and `endByte`. Earlier versions of this library only provided `start` and `end` and they were always bytes, making string slicing unnecessarily difficult.

Second, beware that Javascript's `String.prototype.slice` doesn't actually work on Unicode codepoints. It works on UTF-16 units, which are not the same thing. Intead, you can rely on `String.prototype[Symbol.iterator]` which _does_ work on Unicode codepoints. So this is safe, even when fancy things like emojis are present:

```js
Array.from(myString).slice(range.startChar, range.endChar).join("");
```

if you want to just slice from a string you can use 
```js
str.slice(range.startUtf16Codepoint, range.endUtf16Codepoint)
```

## Contributing

See the [CONTRIBUTING.md](./CONTRIBUTING.md) file.

---
_Source: https://npm.io/package/content-tag · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
