mirror of
https://github.com/stack-auth/stack.git
synced 2026-06-13 21:01:21 +08:00
<!--
Make sure you've read the CONTRIBUTING.md guidelines:
https://github.com/stack-auth/stack-auth/blob/dev/CONTRIBUTING.md
-->
<!-- ELLIPSIS_HIDDEN -->
----
> [!IMPORTANT]
> Introduces Stack Companion with a right-side panel for docs, feature
requests, changelog, and support, along with a new feedback form and
improved feature request handling.
>
> - **New Features**:
> - Adds `StackCompanion` component for right-side panel with Docs,
Feature Requests, Changelog, and Support in `sidebar-layout.tsx` and
`stack-companion.tsx`.
> - Introduces `FeedbackForm` component in `feedback-form.tsx` with
success/error states and contact links.
> - **Feature Requests**:
> - Implements `GET`, `POST`, and `upvote` routes in `route.tsx` and
`[featureRequestId]/upvote/route.tsx` for feature requests with SSO and
upvote syncing.
> - Adds `FeatureRequestBoard` component in `feature-request-board.tsx`
for managing feature requests.
> - **Changelog**:
> - Adds `ChangelogWidget` component in `changelog-widget.tsx` to
display recent updates.
> - **Version Checking**:
> - Refactors version checking logic into `version-check.ts` and updates
`VersionAlerter` in `version-alerter.tsx`.
> - **Miscellaneous**:
> - Allows remote images from `featurebase-attachments.com` in
`next.config.mjs`.
> - Removes old `FeedbackDialog` and `docs/middleware.ts`.
>
> <sup>This description was created by </sup>[<img alt="Ellipsis"
src="https://img.shields.io/badge/Ellipsis-blue?color=175173">](https://www.ellipsis.dev?ref=stack-auth%2Fstack-auth&utm_source=github&utm_medium=referral)<sup>
for 8baf5e1a0f. You can
[customize](https://app.ellipsis.dev/stack-auth/settings/summaries) this
summary. It will automatically update as commits are pushed.</sup>
----
<!-- ELLIPSIS_HIDDEN -->
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
- New Features
- Right-side Stack Companion panel: Docs, Feature Requests (browse,
submit, upvote), Changelog, and Support.
- In-app Feedback form with success/error states and contact links.
- Improvements
- Feature Requests: SSO integration and upvote syncing with backend.
- Changelog viewer: loads and formats recent entries.
- Remote images allowed from featurebase-attachments.com.
- Consolidated version-checking for streamlined alerts.
- Removals
- Old Feedback dialog and docs middleware removed.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: GitButler <gitbutler@gitbutler.com>
Co-authored-by: Konsti Wohlwend <n2d4xc@gmail.com>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
61 lines
1.9 KiB
TypeScript
61 lines
1.9 KiB
TypeScript
import { templateIdentity } from "./strings";
|
|
|
|
export function escapeHtml(unsafe: string): string {
|
|
return `${unsafe}`
|
|
.replace(/&/g, '&')
|
|
.replace(/</g, '<')
|
|
.replace(/>/g, '>')
|
|
.replace(/"/g, """)
|
|
.replace(/'/g, "'");
|
|
}
|
|
import.meta.vitest?.test("escapeHtml", ({ expect }) => {
|
|
// Test with empty string
|
|
expect(escapeHtml("")).toBe("");
|
|
|
|
// Test with string without special characters
|
|
expect(escapeHtml("hello world")).toBe("hello world");
|
|
|
|
// Test with special characters
|
|
expect(escapeHtml("<div>")).toBe("<div>");
|
|
expect(escapeHtml("a & b")).toBe("a & b");
|
|
expect(escapeHtml('a "quoted" string')).toBe("a "quoted" string");
|
|
expect(escapeHtml("it's a test")).toBe("it's a test");
|
|
|
|
// Test with multiple special characters
|
|
expect(escapeHtml("<a href=\"test\">It's a link</a>")).toBe(
|
|
"<a href="test">It's a link</a>"
|
|
);
|
|
});
|
|
|
|
export function html(strings: TemplateStringsArray, ...values: any[]): string {
|
|
return templateIdentity(strings, ...values.map(v => escapeHtml(`${v}`)));
|
|
}
|
|
import.meta.vitest?.test("html", ({ expect }) => {
|
|
// Test with no interpolation
|
|
expect(html`simple string`).toBe("simple string");
|
|
|
|
// Test with string interpolation
|
|
expect(html`Hello, ${"world"}!`).toBe("Hello, world!");
|
|
|
|
// Test with number interpolation
|
|
expect(html`Count: ${42}`).toBe("Count: 42");
|
|
|
|
// Test with HTML special characters in interpolated values
|
|
expect(html`<div>${"<script>"}</div>`).toBe("<div><script></div>");
|
|
|
|
// Test with multiple interpolations
|
|
expect(html`${1} + ${2} = ${"<3"}`).toBe("1 + 2 = <3");
|
|
|
|
// Test with object interpolation
|
|
const obj = { toString: () => "<object>" };
|
|
expect(html`Object: ${obj}`).toBe("Object: <object>");
|
|
});
|
|
|
|
export function htmlToText(untrustedHtml: string): string {
|
|
|
|
const doc = new DOMParser().parseFromString(untrustedHtml, 'text/html');
|
|
|
|
return doc.body.textContent ?? '';
|
|
|
|
}
|