-
-
Notifications
You must be signed in to change notification settings - Fork 43
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: support links in checkbox/boolean nodes (#251)
- Loading branch information
1 parent
9190b15
commit cc92b9c
Showing
5 changed files
with
209 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
74 changes: 74 additions & 0 deletions
74
...elements-react/src/theme/default/components/ui/__snapshots__/checkbox-label.spec.tsx.snap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
// Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
||
exports[`computeLabelElements handles a label with no text but a link 1`] = ` | ||
<div> | ||
<a | ||
class="text-links-link-default hover:text-links-link-hover hover:underline" | ||
href="https://example.com" | ||
rel="noopener noreferrer" | ||
target="_blank" | ||
> | ||
Click here | ||
</a> | ||
</div> | ||
`; | ||
|
||
exports[`computeLabelElements renders a text with a single markdown link correctly 1`] = ` | ||
<div> | ||
This is a | ||
<a | ||
class="text-links-link-default hover:text-links-link-hover hover:underline" | ||
href="https://example.com" | ||
rel="noopener noreferrer" | ||
target="_blank" | ||
> | ||
link | ||
</a> | ||
</div> | ||
`; | ||
|
||
exports[`computeLabelElements renders a text with link and extra text around it correctly 1`] = ` | ||
<div> | ||
Click | ||
<a | ||
class="text-links-link-default hover:text-links-link-hover hover:underline" | ||
href="https://example.com" | ||
rel="noopener noreferrer" | ||
target="_blank" | ||
> | ||
here | ||
</a> | ||
to visit, or go elsewhere. | ||
</div> | ||
`; | ||
|
||
exports[`computeLabelElements renders a text with multiple markdown links correctly 1`] = ` | ||
<div> | ||
This | ||
<a | ||
class="text-links-link-default hover:text-links-link-hover hover:underline" | ||
href="https://first.com" | ||
rel="noopener noreferrer" | ||
target="_blank" | ||
> | ||
first link | ||
</a> | ||
and this | ||
<a | ||
class="text-links-link-default hover:text-links-link-hover hover:underline" | ||
href="https://second.com" | ||
rel="noopener noreferrer" | ||
target="_blank" | ||
> | ||
second link | ||
</a> | ||
</div> | ||
`; | ||
|
||
exports[`computeLabelElements renders null if label is undefined 1`] = `<div />`; | ||
|
||
exports[`computeLabelElements renders plain text without links correctly 1`] = ` | ||
<div> | ||
This is just plain text | ||
</div> | ||
`; |
59 changes: 59 additions & 0 deletions
59
packages/elements-react/src/theme/default/components/ui/checkbox-label.spec.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
// Copyright © 2024 Ory Corp | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
import { render } from "../../../../tests/jest/test-utils" | ||
import { CheckboxLabel } from "./checkbox-label" | ||
|
||
describe("computeLabelElements", () => { | ||
test("renders plain text without links correctly", () => { | ||
const labelText = "This is just plain text" | ||
|
||
const { container } = render( | ||
<CheckboxLabel label={{ text: labelText, id: 0, type: "info" }} />, | ||
) | ||
expect(container).toMatchSnapshot() | ||
}) | ||
|
||
test("renders a text with a single markdown link correctly", () => { | ||
const labelText = "This is a [link](https://example.com)" | ||
|
||
const { container } = render( | ||
<CheckboxLabel label={{ text: labelText, id: 0, type: "info" }} />, | ||
) | ||
expect(container).toMatchSnapshot() | ||
}) | ||
|
||
test("renders a text with multiple markdown links correctly", () => { | ||
const labelText = | ||
"This [first link](https://first.com) and this [second link](https://second.com)" | ||
|
||
const { container } = render( | ||
<CheckboxLabel label={{ text: labelText, id: 0, type: "info" }} />, | ||
) | ||
expect(container).toMatchSnapshot() | ||
}) | ||
|
||
test("renders a text with link and extra text around it correctly", () => { | ||
const labelText = | ||
"Click [here](https://example.com) to visit, or go elsewhere." | ||
|
||
const { container } = render( | ||
<CheckboxLabel label={{ text: labelText, id: 0, type: "info" }} />, | ||
) | ||
expect(container).toMatchSnapshot() | ||
}) | ||
|
||
test("handles a label with no text but a link", () => { | ||
const labelText = "[Click here](https://example.com)" | ||
|
||
const { container } = render( | ||
<CheckboxLabel label={{ text: labelText, id: 0, type: "info" }} />, | ||
) | ||
expect(container).toMatchSnapshot() | ||
}) | ||
|
||
test("renders null if label is undefined", () => { | ||
const { container } = render(<CheckboxLabel label={undefined} />) | ||
expect(container).toMatchSnapshot() | ||
}) | ||
}) |
67 changes: 67 additions & 0 deletions
67
packages/elements-react/src/theme/default/components/ui/checkbox-label.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
// Copyright © 2024 Ory Corp | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
import { UiText } from "@ory/client-fetch" | ||
import { useIntl } from "react-intl" | ||
import { uiTextToFormattedMessage } from "../../../../util" | ||
|
||
type CheckboxLabelProps = { | ||
label?: UiText | ||
} | ||
|
||
const linkRegex = /\[([^\]]+)\]\(([^)]+)\)/g | ||
|
||
export function computeLabelElements(labelText: string) { | ||
const elements = [] | ||
let lastIndex = 0 | ||
|
||
// Use matchAll to find all markdown links | ||
for (const match of labelText.matchAll(linkRegex)) { | ||
const linkText = match[1] | ||
const url = match[2] | ||
const matchStart = match.index | ||
if (typeof matchStart === "undefined") { | ||
// Some types seem to be wrong somewhere, eslint complains that matchStart can be undefined, but it can't? | ||
// So we just skip this match, if it is undefined | ||
continue | ||
} | ||
|
||
// Push the text before the match | ||
if (matchStart > lastIndex) { | ||
elements.push(labelText.slice(lastIndex, matchStart)) | ||
} | ||
|
||
// Push the <a> tag for the markdown link | ||
elements.push( | ||
<a | ||
key={matchStart} | ||
href={url} | ||
target="_blank" | ||
rel="noopener noreferrer" | ||
className="text-links-link-default hover:text-links-link-hover hover:underline" | ||
> | ||
{linkText} | ||
</a>, | ||
) | ||
|
||
// Update lastIndex to the end of the current match | ||
lastIndex = matchStart + match[0].length | ||
} | ||
|
||
// Push any remaining text after the last match | ||
if (lastIndex < labelText.length) { | ||
elements.push(labelText.slice(lastIndex)) | ||
} | ||
return elements | ||
} | ||
|
||
export function CheckboxLabel({ label }: CheckboxLabelProps) { | ||
const intl = useIntl() | ||
if (!label) { | ||
return null | ||
} | ||
|
||
const labelText = uiTextToFormattedMessage(label, intl) | ||
|
||
return <>{computeLabelElements(labelText)}</> | ||
} |