Initial Commit
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
# `sanitizer/sanitizer.ts`
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
|
||||
## Purpose
|
||||
|
||||
Sanitizer hooks applied to inbound `text/html` clipboard payloads. The
|
||||
package ships an identity sanitizer (pass-through) plus a regex-based
|
||||
tag-allowlist sanitizer for stripping known-dangerous tags from
|
||||
untrusted clipboard HTML. Both adhere to the `ClipboardSanitizer` shape
|
||||
`(html: string) => string` so consumers can plug in DOMPurify, sanitize-html,
|
||||
or any other library without changing call sites. The package
|
||||
deliberately does not bundle a security-grade sanitizer to avoid pinning
|
||||
consumers to a specific implementation — `createTagAllowlistSanitizer` is
|
||||
suitable for hardening trusted-origin clipboard flows and is NOT a
|
||||
substitute for DOMPurify in security-critical paths.
|
||||
|
||||
## Features
|
||||
|
||||
- `identitySanitizer` — pass-through, used when no sanitizer is supplied.
|
||||
- `createTagAllowlistSanitizer(tags)` — regex-based stripper that drops
|
||||
any tag not in the supplied allowlist while preserving allowed tags
|
||||
with their attributes intact.
|
||||
- Case-insensitive tag matching.
|
||||
|
||||
## Usage: Basic
|
||||
|
||||
```ts
|
||||
import {
|
||||
ClipboardManager,
|
||||
createTagAllowlistSanitizer,
|
||||
} from "@suaveplan/clipboard";
|
||||
|
||||
const sanitize = createTagAllowlistSanitizer(["p", "b", "i", "br"]);
|
||||
const clipboard = new ClipboardManager({ sanitizer: sanitize });
|
||||
const result = await clipboard.readRichContent();
|
||||
// result.data.html no longer contains <script> or <iframe>.
|
||||
```
|
||||
|
||||
## Usage: Advanced
|
||||
|
||||
```ts
|
||||
import DOMPurify from "dompurify";
|
||||
import { ClipboardManager } from "@suaveplan/clipboard";
|
||||
|
||||
const clipboard = new ClipboardManager({
|
||||
sanitizer: (html) =>
|
||||
DOMPurify.sanitize(html, { ALLOWED_TAGS: ["p", "a", "b", "i"] }),
|
||||
});
|
||||
|
||||
const result = await clipboard.readRichContent();
|
||||
if (result.success) {
|
||||
const cleaned = result.data?.html ?? "";
|
||||
// Pass `cleaned` to a downstream React component or DOM renderer
|
||||
// that knows how to safely interpolate sanitized HTML.
|
||||
return cleaned;
|
||||
}
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### `identitySanitizer(html: string): string`
|
||||
|
||||
Pass-through; returns input unchanged. Used internally as the default
|
||||
sanitizer when no override is supplied.
|
||||
|
||||
### `createTagAllowlistSanitizer(allowed: readonly string[]): ClipboardSanitizer`
|
||||
|
||||
Returns a sanitizer that strips every HTML tag not present in `allowed`.
|
||||
Tag matching is case-insensitive; opening and closing tags are stripped
|
||||
together. Attributes on allowed tags are preserved. The function only
|
||||
removes the angle-bracketed tag itself — any content nested inside
|
||||
disallowed tags is left in place. For full DOM-level sanitization use a
|
||||
real library such as DOMPurify.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
The regex used is intentionally conservative — it matches
|
||||
`<[a-zA-Z][a-zA-Z0-9-]*` to capture tag names and tolerates optional
|
||||
attribute payloads via `(\s[^>]*)?`. It does not attempt to handle CDATA,
|
||||
comments, or processing instructions. This matches the documented scope:
|
||||
trusted-origin clipboard hardening, not arbitrary-source HTML
|
||||
sanitization. The `Set` of lowercased allowed tags keeps lookup at O(1).
|
||||
The module is browser-tier but has no DOM dependency, so it also works
|
||||
inside service workers and Node-side SSR consumers that happen to
|
||||
process clipboard payloads on the server.
|
||||
Reference in New Issue
Block a user