Skip to content

Commit 4729976

Browse files
authored
chore: release 1.0.1 (#2)
* docs: add a changelog, an upgrade guide and package metadata Lists the 1.0.0 breaking changes and adds an Upgrading from 0.x section to the README. Names the type file for every export condition, ships CHANGELOG.md, and updates the author and copyright years. * chore: name Maksym Synenko as author * chore: release 1.0.1 * ci: publish to npm and create the GitHub release on a version tag npm run release now only tags and pushes. The Release workflow checks the tag against package.json, runs the tests and size limits, publishes with npm trusted publishing and creates the release from the CHANGELOG.md section.
1 parent 7d6e181 commit 4729976

6 files changed

Lines changed: 155 additions & 12 deletions

File tree

‎.github/workflows/release.yml‎

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
name: Release
2+
3+
on:
4+
push:
5+
tags:
6+
- "[0-9]+.[0-9]+.[0-9]+"
7+
8+
permissions:
9+
contents: write
10+
# npm trusted publishing: the package is published with an OIDC token and
11+
# gets provenance, so no NPM_TOKEN secret is stored.
12+
id-token: write
13+
14+
jobs:
15+
publish:
16+
runs-on: ubuntu-latest
17+
steps:
18+
- uses: actions/checkout@v4
19+
- uses: actions/setup-node@v4
20+
with:
21+
node-version: lts/*
22+
cache: npm
23+
registry-url: https://registry.npmjs.org
24+
25+
# Trusted publishing needs npm 11.5.1 or newer.
26+
- run: npm install -g npm@latest
27+
28+
- name: Check the tag matches package.json
29+
run: |
30+
version=$(node -p "require('./package.json').version")
31+
if [ "$version" != "$GITHUB_REF_NAME" ]; then
32+
echo "Tag $GITHUB_REF_NAME does not match package.json version $version"
33+
exit 1
34+
fi
35+
36+
- run: npm ci
37+
- run: npm test
38+
- run: npm run build:size
39+
- run: npm publish
40+
41+
- name: Create the GitHub release from CHANGELOG.md
42+
env:
43+
GH_TOKEN: ${{ github.token }}
44+
run: |
45+
awk -v v="$GITHUB_REF_NAME" '/^## /{ if (f) exit; f = ($2 == v); next } f' CHANGELOG.md > notes.md
46+
gh release create "$GITHUB_REF_NAME" --verify-tag --title "$GITHUB_REF_NAME" --notes-file notes.md

‎CHANGELOG.md‎

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# Changelog
2+
3+
## 1.0.1
4+
5+
- `exports` names the type file for each entry and module format, so TypeScript picks `.d.ts` for `import` and `.d.cts` for `require` without guessing.
6+
- The package ships `CHANGELOG.md`, and `author` names the maintainer.
7+
8+
## 1.0.0
9+
10+
The default entry now sanitizes, and React Native gets its own entry.
11+
12+
### Breaking changes
13+
14+
- **React 18 or newer.** The `react` peer range moves from `>=16.8.0` to `>=18.0.0`. The native entry also needs `react-native >=0.71`.
15+
- **`parse` sanitizes by default.** `parse` from `react-html5-parser` runs DOMPurify over the parsed tree. Output that used to render can now be stripped:
16+
- `<script>`, event handlers (`onclick`), `javascript:` URLs, `<iframe>`, `<embed>` and `<object>`;
17+
- `<style>` and `<title>`, which act on the whole page;
18+
- the `form` and `formaction` attributes;
19+
- `style` attributes that set `position: fixed`;
20+
- attributes outside DOMPurify's allowlist, such as `contenteditable` and `fetchpriority`;
21+
- unknown and custom elements, unless the tag is mapped in `components` (their content is kept).
22+
- **Bigger default entry.** It grows from about 1.4 kB to about 15 kB min + gzip, because DOMPurify is bundled. Import from `react-html5-parser/core` to keep the old size and behaviour.
23+
- **`sanitize` no longer replaces the sanitizer on the default entry.** DOMPurify runs after your `sanitize` function. To use only your own sanitizer, import from `/core`.
24+
- **`components` entries render as React components.** They were called as plain functions before. Hooks inside them now work, but an inline arrow function remounts its subtree on every render, and a component that returns `undefined` throws on React 18. Define components outside render and return `null` for nothing.
25+
- **`mapElement` receives the component element** for a tag mapped in `components`, not the element the component returned.
26+
- **`MapComponentFn` props no longer include `key`.** The type is now `ComponentProps` (`PropsWithChildren<Attributes>`).
27+
28+
### Added
29+
30+
- `react-html5-parser/core`: the unsanitized parser, about 3 kB.
31+
- `react-html5-parser/native`: renders HTML to React Native `View`, `Text` and `Image`, with `components`, `tagStyles`, `textStyle`, `onLinkPress` and `mapElement` options. Links open only for `http`, `https`, `mailto` and `tel`; images load only from `http`, `https` and raster data URIs.
32+
- `purify` option on the default entry: a DOMPurify config merged over the built-in one.
33+
- CommonJS builds next to ESM for every entry.
34+
35+
### Fixed
36+
37+
- SVG attributes (`viewBox`, `stroke-width`, `xlink:href` and the rest) map to their React names by default.
38+
- Form fields render uncontrolled (`defaultValue`, `defaultChecked`), so React no longer warns about a `value` without `onChange`.
39+
- On React 19, `<script async>` is rendered inert instead of hoisted and run, and `<html>` / `<body>` no longer bind to the page's own.
40+
- Custom elements keep their attribute names as written.
41+
- `attrsMap` applies to every element, including mapped components.
42+
43+
### Upgrading
44+
45+
See [Upgrading from 0.x](README.md#upgrading-from-0x).

‎LICENSE.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
MIT License
22

3-
Copyright (c) 2022 Max Syn
3+
Copyright (c) 2022-2026 Maksym Synenko
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

‎README.md‎

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,34 @@ An error thrown inside `onError` reaches the caller. A component from `component
370370
- `hidden="until-found"` becomes plain `hidden`: React 19 treats `hidden` as a boolean.
371371
- In the core entry, `async` is dropped from `<script>`, so React 19 renders it inert instead of hoisting and running it, and `<title>`, `<meta>` and `<link>` are hoisted into the document `<head>` by React 19.
372372

373+
## Upgrading from 0.x
374+
375+
1.0 sanitizes by default and needs React 18. Every change is in the [changelog](CHANGELOG.md#100).
376+
377+
**Keep the 0.x output.** Import from the core entry. It is the 0.x parser with the 1.0 fixes, and runs only the `sanitize` you pass:
378+
379+
```diff
380+
- import { parse } from "react-html5-parser";
381+
+ import { parse } from "react-html5-parser/core";
382+
```
383+
384+
**Stay on the default entry.** Check what DOMPurify now removes from your content (see [Built-in sanitizer](#built-in-sanitizer)), then:
385+
386+
- Drop your own DOMPurify call from `sanitize`; the built-in one runs anyway. Keep `sanitize` only for rewrites.
387+
- Allow a tag or attribute you need through `purify`, or map the tag in `components`:
388+
389+
```ts
390+
parse(html, { purify: { ADD_ATTR: ["contenteditable"] } });
391+
```
392+
393+
**`components`.** Entries are now rendered as React components, not called as functions:
394+
395+
- Define the map at module scope. An inline object or arrow function gives the tag a new component type on every render, and React remounts its subtree.
396+
- Return `null`, not `undefined`, to render nothing. React 18 throws on `undefined`.
397+
- `mapElement` now receives the `<YourComponent>` element for a mapped tag, not what your component returned.
398+
399+
**Types.** `MapComponentFn` props are now `ComponentProps` and no longer include `key`.
400+
373401
## Development
374402

375403
```sh
@@ -381,6 +409,8 @@ npm run build # tsdown to dist/ (ESM + CJS + types), then publint
381409
npm run build:size # build, then check the size limits above
382410
```
383411

412+
To release, bump `version` in `package.json`, add its section to `CHANGELOG.md`, merge, then run `npm run release` on `main`. It tags the version and pushes the tag; the Release workflow publishes to npm with provenance and creates the GitHub release from the changelog section.
413+
384414
## Contributing
385415

386416
Issues and pull requests are welcome at [github.com/devmaxxx/react-html5-parser](https://github.com/devmaxxx/react-html5-parser). For a bug, include the HTML string and the options you passed to `parse`. A pull request should come with a test in `__tests__/` and keep `npm test` and `npm run build:size` green.

‎package-lock.json‎

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎package.json‎

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "react-html5-parser",
3-
"version": "1.0.0",
3+
"version": "1.0.1",
44
"description": "Turn HTML strings into React and React Native elements, sanitized by default. No dangerouslySetInnerHTML.",
55
"keywords": [
66
"react",
@@ -31,23 +31,41 @@
3131
"url": "git+https://github.com/devmaxxx/react-html5-parser.git"
3232
},
3333
"license": "MIT",
34-
"author": "devmaxxx",
34+
"author": "Maksym Synenko (https://github.com/devmaxxx)",
3535
"sideEffects": false,
3636
"type": "module",
3737
"main": "./dist/index.cjs",
3838
"module": "./dist/index.js",
3939
"exports": {
4040
".": {
41-
"import": "./dist/index.js",
42-
"require": "./dist/index.cjs"
41+
"import": {
42+
"types": "./dist/index.d.ts",
43+
"default": "./dist/index.js"
44+
},
45+
"require": {
46+
"types": "./dist/index.d.cts",
47+
"default": "./dist/index.cjs"
48+
}
4349
},
4450
"./core": {
45-
"import": "./dist/core.js",
46-
"require": "./dist/core.cjs"
51+
"import": {
52+
"types": "./dist/core.d.ts",
53+
"default": "./dist/core.js"
54+
},
55+
"require": {
56+
"types": "./dist/core.d.cts",
57+
"default": "./dist/core.cjs"
58+
}
4759
},
4860
"./native": {
49-
"import": "./dist/native.js",
50-
"require": "./dist/native.cjs"
61+
"import": {
62+
"types": "./dist/native.d.ts",
63+
"default": "./dist/native.js"
64+
},
65+
"require": {
66+
"types": "./dist/native.d.cts",
67+
"default": "./dist/native.cjs"
68+
}
5169
},
5270
"./package.json": "./package.json"
5371
},
@@ -57,6 +75,7 @@
5775
"dist",
5876
"native",
5977
"README.md",
78+
"CHANGELOG.md",
6079
"EXAMPLES.md"
6180
],
6281
"scripts": {
@@ -66,7 +85,7 @@
6685
"build:size": "npm run build && npm run sizecheck",
6786
"test": "npm run typecheck && jest",
6887
"test:watch": "jest --watchAll",
69-
"release": "npm run test && npm run build:size && git tag $npm_package_version && git push && git push --tags && npm publish",
88+
"release": "npm run test && npm run build:size && git tag $npm_package_version && git push && git push origin $npm_package_version",
7089
"typecheck": "tsc --noEmit -p .",
7190
"clean": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\""
7291
},
@@ -155,5 +174,8 @@
155174
"domhandler": "6.0.1",
156175
"entities": "8.1.0",
157176
"htmlparser2": "12.0.0"
177+
},
178+
"publishConfig": {
179+
"access": "public"
158180
}
159181
}

0 commit comments

Comments
 (0)