Skip to content

Commit

Permalink
Merge pull request #12 from charlie-tango/feat/rich-text-to-plain-text
Browse files Browse the repository at this point in the history
  • Loading branch information
thebuilder authored Nov 8, 2024
2 parents 461b968 + 9cfe150 commit f8020fd
Show file tree
Hide file tree
Showing 13 changed files with 536 additions and 216 deletions.
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

0 comments on commit f8020fd

Please sign in to comment.