Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add richTextToPlainText #12

Merged
merged 8 commits into from
Nov 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/pkg-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ jobs:
- name: Build
run: pnpm build
- name: Publish preview package
run: pnpx pkg-pr-new publish --no-template
run: pnpx pkg-pr-new publish --no-template --compact
48 changes: 46 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ choice.
npm install @charlietango/react-umbraco
```

### `<UmbracoRichText>`
## `<UmbracoRichText>`

[![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz_small.svg)](https://stackblitz.com/github/charlie-tango/react-umbraco/tree/main?file=examples/UmbracoRichText/src/RichText.tsx)

Expand Down Expand Up @@ -84,7 +84,7 @@ function RichText({ data }) {
}
```

#### Blocks
### Blocks

You can augment the `renderBlock` method with the generated OpenAPI types from
Umbraco Content Delivery API. That way you can correctly filter the blocks you
Expand All @@ -110,6 +110,50 @@ declare module "@charlietango/react-umbraco" {
}
```

## `richTextToPlainText`

A utility function to convert an Umbraco RichText element to plain text. This
can be useful for generating meta descriptions or other text-based properties.

### Parameters

- `data` (`RichTextElementModel`): The rich text element to be converted.
- `options` (`Options`, _optional_): An object to specify additional options.
- `firstParagraph` (`boolean`, _optional_): If `true`, only the first
paragraph with text content will be returned.
- `maxLength` (`number`, _optional_): The maximum length of the returned text.
If the text exceeds this length, it will be truncated to the nearest word
and an ellipsis will be added.
- `ignoreTags` (`Array<string>`, _optional_): An array of tags to be ignored
during the conversion.

### Returns

- `string`: The plain text representation of the rich text element.

### Example

```ts
import { richTextToPlainText } from "@charlietango/react-umbraco";

const plainText = richTextToPlainText(richTextData);

// Just the first paragraph
const firstParagraph = richTextToPlainText(richTextData, {
firstParagraph: true,
});

// Just the first 100 characters, truncated at the nearest word with an ellipsis
const first100Characters = richTextToPlainText(richTextData, {
maxLength: 100,
});

// Ignore certain tags, skipping their content
const ignoreTags = richTextToPlainText(richTextData, {
ignoreTags: ["h1", "h2", "ol", "figure"],
});
```

<!-- Badges -->

[npm-version-src]:
Expand Down
15 changes: 9 additions & 6 deletions examples/UmbracoRichText/src/RichText.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import {
type RenderBlockContext,
type UmbracoBlockContext,
type RenderNodeContext,
UmbracoRichText,
} from '@charlietango/react-umbraco';

// replace with ApiBlockItemModel from your own Umbraco API openapi docs for type safety
type ApiBlockItemModel = {
interface ApiBlockItemModel {
content: {
id: 'youtube';
properties: {
videoId: string;
};
};
};
}

declare module '@charlietango/react-umbraco' {
interface UmbracoBlockItemModel extends ApiBlockItemModel {}
Expand All @@ -27,7 +27,7 @@ function renderNode({
// discriminating on the tag name ensures correct typing for attributes
switch (tag) {
case 'img': {
return <img {...attributes} loading="lazy" />;
return <img alt="" {...attributes} loading="lazy" />;
}
case 'p':
return <p {...attributes}>{children}</p>;
Expand All @@ -42,7 +42,9 @@ function exhaustiveGuard(value: never): never {
// provide handling of rendering blocks from Umbraco
function renderBlock({
content,
}: RenderBlockContext): React.ReactNode | undefined {
}: UmbracoBlockContext): React.ReactNode | undefined {
if (!content) return undefined;

// discriminating on content.id ensures correct typing for the content properties based on the defined ApiBlockItemModel
switch (content.id) {
case 'youtube':
Expand All @@ -54,9 +56,10 @@ function renderBlock({
target="_blank"
>
<figure className="group-hover:scale-125 transition z-10 text-white bg-red-500 block w-9 h-7 rounded-md text-center absolute top-1/2 left-1/2 m-0 -translate-x-1/2 -translate-y-1/2">
</figure>
<img
alt=""
className="rounded-xl"
src={`https://i.ytimg.com/vi/${content.properties.videoId}/hq720.jpg`}
/>
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,12 @@
},
"devDependencies": {
"@biomejs/biome": "^1.9.4",
"@types/node": "^22.8.5",
"@types/node": "^22.9.0",
"@types/react": "^18.3.12",
"@types/react-dom": "^18.3.1",
"@vitejs/plugin-react": "^4.3.3",
"@vitest/browser": "^2.1.4",
"bumpp": "^9.8.0",
"bumpp": "^9.8.1",
"lint-staged": "^15.2.10",
"playwright": "^1.48.2",
"prettier": "^3.3.3",
Expand Down
Loading