Skip to content

Commit

Permalink
chore: fixed line break handling + bumped dependencies
Browse files Browse the repository at this point in the history
  • Loading branch information
freb97 committed May 29, 2024
1 parent 07726eb commit da2fc85
Show file tree
Hide file tree
Showing 8 changed files with 491 additions and 693 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
# 1.0.6
- Fixed an issue with line breaks not rendering
- Bumped dependencies
- Updated documentation

# 1.0.5
- Bumped dependencies
- Changed type check to vue-tsc
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

A fully customizable Nuxt 3 module for rendering text with the new Blocks rich text editor element from Strapi CMS.

The implementation is based on Strapi's [Blocks React Renderer](https://github.com/strapi/blocks-react-renderer/).

## Installation

1. Install the Blocks renderer:
Expand Down
1,081 changes: 422 additions & 659 deletions package-lock.json

Large diffs are not rendered by default.

19 changes: 10 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "nuxt-strapi-blocks-renderer",
"version": "1.0.5",
"version": "1.0.6",
"description": "Renderer for the strapi CMS blocks text content element.",
"license": "MIT",
"repository": {
Expand Down Expand Up @@ -38,20 +38,21 @@
"defu": "^6.1.4"
},
"devDependencies": {
"@types/node": "^20.12.11",
"@nuxt/devtools": "^1.3.1",
"@nuxt/eslint-config": "^0.3.12",
"@nuxt/module-builder": "^0.6.0",
"@nuxt/devtools": "^1.3.2",
"@nuxt/eslint-config": "^0.3.13",
"@nuxt/module-builder": "^0.7.0",
"@nuxt/schema": "^3.11.2",
"@nuxt/test-utils": "^3.12.1",
"@stylistic/eslint-plugin": "^1.8.1",
"@nuxt/test-utils": "^3.13.1",
"@stylistic/eslint-plugin": "^2.1.0",
"@types/node": "^20.12.11",
"@typescript-eslint/eslint-plugin": "^7.11.0",
"eslint": "^8.57.0",
"nuxt": "^3.11.2",
"typescript": "^5.4.5",
"vitest": "^1.6.0",
"vue": "^3.4.27",
"vue-tsc": "^2.0.17",
"vue-eslint-parser": "^9.4.2",
"typescript": "^5.4.5"
"vue-tsc": "^2.0.19"
},
"packageManager": "[email protected]",
"engines": {
Expand Down
9 changes: 9 additions & 0 deletions src/runtime/.fixtures/sampleBlockNodes.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,15 @@
}
]
},
{
"type": "paragraph",
"children": [
{
"type": "text",
"text": "Paragraph with \nline \nbreaks"
}
]
},
{
"type": "paragraph",
"children": [
Expand Down
38 changes: 27 additions & 11 deletions src/runtime/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,30 @@ const prefix = (): string => {
return (strapiBlocksRenderer as ModuleOptions).blocksPrefix;
};

export const textInlineNode = (node: TextInlineNode): VNode | string => {
if (node.bold) return h(resolveComponent(prefix() + 'BoldInlineNode'), () => node.text);
if (node.italic) return h(resolveComponent(prefix() + 'ItalicInlineNode'), () => node.text);
if (node.underline) return h(resolveComponent(prefix() + 'UnderlineInlineNode'), () => node.text);
if (node.strikethrough) return h(resolveComponent(prefix() + 'StrikethroughInlineNode'), () => node.text);
if (node.code) return h(resolveComponent(prefix() + 'CodeInlineNode'), () => node.text);

return node.text;
const getNodeText = (node: TextInlineNode): (VNode | string)[] => {
const lines: (VNode | string)[] = [];

node.text.split('\n').forEach((line: string, index: number, array: string[]): void => {
lines.push(line);

if (index !== array.length - 1) {
lines.push(h('br'));
}
});

return lines;
};

export const textInlineNode = (node: TextInlineNode): (VNode | string)[] | VNode => {
const text: (VNode | string)[] = getNodeText(node);

if (node.bold) return h(resolveComponent(prefix() + 'BoldInlineNode'), () => text);
if (node.italic) return h(resolveComponent(prefix() + 'ItalicInlineNode'), () => text);
if (node.underline) return h(resolveComponent(prefix() + 'UnderlineInlineNode'), () => text);
if (node.strikethrough) return h(resolveComponent(prefix() + 'StrikethroughInlineNode'), () => text);
if (node.code) return h(resolveComponent(prefix() + 'CodeInlineNode'), () => text);

return text;
};

export const linkInlineNode = (node: LinkInlineNode): VNode => {
Expand All @@ -42,7 +58,7 @@ export const linkInlineNode = (node: LinkInlineNode): VNode => {
}));
};

export const defaultInlineNode = (node: DefaultInlineNode): VNode | string | undefined => {
export const defaultInlineNode = (node: DefaultInlineNode): (VNode | string)[] | VNode | undefined => {
if (node.type === 'link') {
return linkInlineNode(node);
}
Expand Down Expand Up @@ -79,7 +95,7 @@ export const codeBlockNode = (node: CodeBlockNode): VNode => {
const codeComponent: string | ConcreteComponent = resolveComponent(prefix() + 'CodeNode');

return h(codeComponent, () => node.children.map(
(childNode: TextInlineNode): VNode | string => textInlineNode(childNode))
(childNode: TextInlineNode): (VNode | string)[] | VNode => textInlineNode(childNode))
);
};

Expand Down Expand Up @@ -116,7 +132,7 @@ export const imageBlockNode = (node: ImageBlockNode): VNode => {
};

export const renderBlocks = (blockNodes: BlockNode[]): VNode[] => {
return blockNodes.map((blockNode: BlockNode) => {
return blockNodes.map((blockNode: BlockNode): VNode => {
switch (blockNode.type) {
case 'heading': return headingBlockNode(blockNode);
case 'paragraph': return paragraphBlockNode(blockNode);
Expand Down
15 changes: 8 additions & 7 deletions test/basic.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ const fetchPage = async (): Promise<string> => {
return html;
};

describe('Basic blocks text rendering', async () => {
describe('Basic blocks text rendering', async (): Promise<void> => {
await setup({
rootDir: fileURLToPath(new URL('./fixtures/basic', import.meta.url)),
});

it('Renders the heading nodes', async () => {
it('Renders the heading nodes', async (): Promise<void> => {
const html: string = await fetchPage();

expect(html).toContain('<h1>Heading 1</h1>');
Expand All @@ -28,10 +28,11 @@ describe('Basic blocks text rendering', async () => {
expect(html).toContain('<h6>Heading 6</h6>');
});

it('Renders the text nodes', async () => {
it('Renders the text nodes', async (): Promise<void> => {
const html: string = await fetchPage();

expect(html).toContain('<p>Paragraph</p>');
expect(html).toContain('<p>Paragraph with <br>line <br>breaks</p>');
expect(html).toContain('<p><strong>Bold</strong></p>');
expect(html).toContain('<p><em>Italic</em></p>');
expect(html).toContain('<p><u>Underline</u></p>');
Expand All @@ -40,7 +41,7 @@ describe('Basic blocks text rendering', async () => {
expect(html).toContain('<p><a href="https://www.example.com/">Link</a></p>');
});

it('Renders the list nodes', async () => {
it('Renders the list nodes', async (): Promise<void> => {
const html: string = await fetchPage();

expect(html).toContain('<ul>' +
Expand All @@ -56,19 +57,19 @@ describe('Basic blocks text rendering', async () => {
'</ol>');
});

it('Renders the quote node', async () => {
it('Renders the quote node', async (): Promise<void> => {
const html: string = await fetchPage();

expect(html).toContain('<blockquote>Quote</blockquote>');
});

it('Renders the code node', async () => {
it('Renders the code node', async (): Promise<void> => {
const html: string = await fetchPage();

expect(html).toContain('<pre> Code\n </pre>');
});

it('Renders the image node', async () => {
it('Renders the image node', async (): Promise<void> => {
const html: string = await fetchPage();

expect(html).toContain('<img ' +
Expand Down
15 changes: 8 additions & 7 deletions test/custom.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ const fetchPage = async (): Promise<string> => {
return html;
};

describe('Custom blocks text rendering', async () => {
describe('Custom blocks text rendering', async (): Promise<void> => {
await setup({
rootDir: fileURLToPath(new URL('./fixtures/custom', import.meta.url)),
});

it('Renders the custom heading nodes', async () => {
it('Renders the custom heading nodes', async (): Promise<void> => {
const html: string = await fetchPage();

expect(html).toContain('<h1 style="color:red;">Heading 1</h1>');
Expand All @@ -28,10 +28,11 @@ describe('Custom blocks text rendering', async () => {
expect(html).toContain('<h6 style="color:red;">Heading 6</h6>');
});

it('Renders the custom text nodes', async () => {
it('Renders the custom text nodes', async (): Promise<void> => {
const html: string = await fetchPage();

expect(html).toContain('<p style="color:red;">Paragraph</p>');
expect(html).toContain('<p style="color:red;">Paragraph with <br>line <br>breaks</p>');
expect(html).toContain('<p style="color:red;"><strong style="color:red;">Bold</strong></p>');
expect(html).toContain('<p style="color:red;"><em style="color:red;">Italic</em></p>');
expect(html).toContain('<p style="color:red;"><u style="color:red;">Underline</u></p>');
Expand All @@ -43,7 +44,7 @@ describe('Custom blocks text rendering', async () => {
'</p>');
});

it('Renders the custom list nodes', async () => {
it('Renders the custom list nodes', async (): Promise<void> => {
const html: string = await fetchPage();

expect(html).toContain('<ul style="color:red;">' +
Expand All @@ -59,19 +60,19 @@ describe('Custom blocks text rendering', async () => {
'</ol>');
});

it('Renders the custom quote node', async () => {
it('Renders the custom quote node', async (): Promise<void> => {
const html: string = await fetchPage();

expect(html).toContain('<blockquote style="color:red;">Quote</blockquote>');
});

it('Renders the custom code node', async () => {
it('Renders the custom code node', async (): Promise<void> => {
const html: string = await fetchPage();

expect(html).toContain('<pre style="color:red;"> Code\n </pre>');
});

it('Renders the custom image node', async () => {
it('Renders the custom image node', async (): Promise<void> => {
const html: string = await fetchPage();

expect(html).toContain('<img ' +
Expand Down

0 comments on commit da2fc85

Please sign in to comment.