Skip to content

Commit

Permalink
Merge pull request #5 from codeskills-dev/fix/p-bold
Browse files Browse the repository at this point in the history
Fix: parsing-inconsistencies and optimisations
  • Loading branch information
lordelogos authored Jul 15, 2023
2 parents 644836c + 82017f8 commit 938b9c8
Show file tree
Hide file tree
Showing 18 changed files with 6,276 additions and 4,510 deletions.
Binary file added .DS_Store
Binary file not shown.
8 changes: 8 additions & 0 deletions .changeset/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Changesets

Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works
with multi-package repos, or single-package repos to help you version and publish your code. You can
find the full documentation for it [in our repository](https://github.com/changesets/changesets)

We have a quick list of common questions to get you started engaging with this project in
[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)
11 changes: 11 additions & 0 deletions .changeset/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"$schema": "https://unpkg.com/@changesets/[email protected]/schema.json",
"changelog": "@changesets/cli/changelog",
"commit": false,
"fixed": [],
"linked": [],
"access": "restricted",
"baseBranch": "master",
"updateInternalDependencies": "patch",
"ignore": []
}
18 changes: 18 additions & 0 deletions .changeset/late-squids-join.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
"md-to-react-email": patch
---

### Bug fixes

- Fixed issue with parsing paragraphs
- Converted bold and italics tag to <strong> and <em>
- Fixed issue with parsing nested blockquotes
- Fixed issue with parsing code blocks

### Optimisations

This PR added optimisations for the following:

- Cleaning up unused style tags for the generated markup
- Moved the changesets
- Added CI workflows
21 changes: 21 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
name: CI
on:
push:
branches:
- "**"

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: pnpm/action-setup@v2
with:
version: 7
- uses: actions/setup-node@v3
with:
node-version: 16.x
cache: "pnpm"

- run: pnpm install --frozen-lockfile
- run: pnpm run lint && pnpm run build
35 changes: 35 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: Publish
on:
workflow_run:
workflows: ["CI"]
types:
- completed
push:
branches:
- "master"

concurrency: ${{ github.workflow }}-${{ github.ref }}

jobs:
publish:
if: ${{ github.event.workflow_run.conclusion == 'success' }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: pnpm/action-setup@v2
with:
version: 7
- uses: actions/setup-node@v3
with:
node-version: 16.x
cache: "pnpm"

- run: pnpm install --frozen-lockfile
- name: Create Release Pull Request or Publish
id: changesets
uses: changesets/action@v1
with:
publish: pnpm run release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
7 changes: 6 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,9 @@
/coverage/

# Build files
/dist
/dist

# JS files
*.js
*.txt
*.html
215 changes: 88 additions & 127 deletions __tests__/parseMarkdownToReactEmail.test.ts
Original file line number Diff line number Diff line change
@@ -1,169 +1,130 @@
import { parseMarkdownToReactEmail, styles } from "../src";
import { parseMarkdownToReactEmail } from "../src";

describe("Markdown to React Mail Parser", () => {
it("converts header one correctly", () => {
it("converts headers correctly", () => {
const markdown = "# Hello, World!";
const expected = `<Section><Heading as="h1" style={${JSON.stringify(
styles.h1
)}}>Hello, World!</Heading></Section>`;
const expected = `<Section><Heading as=\"h1\" style={{\"fontWeight\":\"500\",\"paddingTop\":20,\"fontSize\":\"2.5rem\"}}>Hello, World!</Heading></Section>`;

const rendered = parseMarkdownToReactEmail(markdown);
expect(rendered).toBe(expected);
});

it("converts header two correctly", () => {
const markdown = "## Heading Two";
const expected = `<Section><Heading as="h2" style={${JSON.stringify(
styles.h2
)}}>Heading Two</Heading></Section>`;
it("converts paragraphs, headers, lists, and tables correctly", () => {
const markdown = `# Header 1
const result = parseMarkdownToReactEmail(markdown);
expect(result).toEqual(expected);
});
This is a paragraph with some text. You can have multiple paragraphs separated by empty lines.
it("converts header three correctly", () => {
const markdown = "### Heading Three";
const expected = `<Section><Heading as="h3" style={${JSON.stringify(
styles.h3
)}}>Heading Three</Heading></Section>`;
## Header 2
const result = parseMarkdownToReactEmail(markdown);
expect(result).toEqual(expected);
});
Here is an unordered list:
- Item 1
- Item 2
- Item 3
it("converts header four correctly", () => {
const markdown = "#### Heading Four";
const expected = `<Section><Heading as="h4" style={${JSON.stringify(
styles.h4
)}}>Heading Four</Heading></Section>`;
### Header 3
const result = parseMarkdownToReactEmail(markdown);
expect(result).toEqual(expected);
});
Here is an ordered list:
1. First
2. Second
3. Third
it("converts header five correctly", () => {
const markdown = "##### Heading Five";
const expected = `<Section><Heading as="h5" style={${JSON.stringify(
styles.h5
)}}>Heading Five</Heading></Section>`;
#### Header 4
const result = parseMarkdownToReactEmail(markdown);
expect(result).toEqual(expected);
});
A table example:
it("converts header six correctly", () => {
const markdown = "###### Heading Six";
const expected = `<Section><Heading as="h6" style={${JSON.stringify(
styles.h6
)}}>Heading Six</Heading></Section>`;
| Column 1 | Column 2 |
|----------|----------|
| Cell 1 | Cell 2 |
| Cell 3 | Cell 4 |
`;

const result = parseMarkdownToReactEmail(markdown);
expect(result).toEqual(expected);
});
const expected = `<Section><Heading as="h1" style={{"fontWeight":"500","paddingTop":20,"fontSize":"2.5rem"}}>Header 1</Heading>
it("should handle block quote", () => {
const markdown = "> This is a block quote.";
const expected = `<Section><Text style={${JSON.stringify(
styles.blockQuote
)}}>This is a block quote.</Text></Section>`;
<Text>This is a paragraph with some text. You can have multiple paragraphs separated by empty lines.</Text>
const result = parseMarkdownToReactEmail(markdown);
expect(result).toEqual(expected);
});
<Heading as="h2" style={{"fontWeight":"500","paddingTop":20,"fontSize":"2rem"}}>Header 2</Heading>
it("converts paragraphs correctly", () => {
const markdown = "This is a paragraph.";
const expected = `<Section>This is a paragraph.</Section>`;
<Text>Here is an unordered list:</Text>
<ul><li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li></ul>
const rendered = parseMarkdownToReactEmail(markdown);
expect(rendered).toBe(expected);
});
<Heading as="h3" style={{"fontWeight":"500","paddingTop":20,"fontSize":"1.75rem"}}>Header 3</Heading>
it("converts bold text correctly", () => {
const markdown = "**bold text**";
const expected = `<Section><Text style={${JSON.stringify(
styles.bold
)}}>bold text</Text></Section>`;
<Text>Here is an ordered list:</Text>
<ol><li>First</li>
<li>Second</li>
<li>Third</li>
</ol>
<Heading as="h4" style={{"fontWeight":"500","paddingTop":20,"fontSize":"1.5rem"}}>Header 4</Heading>
<Text>A table example:</Text>
<table><thead><tr><th align="center">Column 1</th><th align="center">Column 2</th></tr></thead><tbody><tr><td align="center">Cell 1</td><td align="center">Cell 2</td></tr><tr><td align="center">Cell 3</td><td align="center">Cell 4</td></tr></tbody></table></Section>`;

const rendered = parseMarkdownToReactEmail(markdown);
expect(rendered).toBe(expected);
});

it("converts italic text correctly", () => {
const markdown = "*italic text*";
const expected = `<Section><Text style={${JSON.stringify(
styles.italic
)}}>italic text</Text></Section>`;
it("converts images, codeblocks, blockquotes and nested blockquotes correctly", () => {
const markdown = `##### Header 5
const rendered = parseMarkdownToReactEmail(markdown);
expect(rendered).toBe(expected);
});
An image example:
![Alt Text](https://example.com/image.jpg)
it("converts lists correctly", () => {
const markdown = "- Item 1\n- Item 2\n- Item 3";
const expected = `<Section><ul style={${JSON.stringify(
styles.ul
)}}><li style={${JSON.stringify(styles.li)}}>Item 1</li>
<li style={${JSON.stringify(styles.li)}}>Item 2</li>
<li style={${JSON.stringify(styles.li)}}>Item 3</li></ul></Section>`;
###### Header 6
const rendered = parseMarkdownToReactEmail(markdown);
expect(rendered).toBe(expected);
});
Some **bold text** and *italic text* _italic text_.
it("converts images correctly", () => {
const markdown = "![alt text](image.jpg)";
const expected = `<Section><Img style={${JSON.stringify(
styles.image
)}} alt="alt text" src="image.jpg" /></Section>`;
Code block example:
\`\`\`
javascript
function greet() {
console.log('Hello!');
}
\`\`\`
const rendered = parseMarkdownToReactEmail(markdown);
expect(rendered).toBe(expected);
});
Here is a block quote example:
it("converts links correctly", () => {
const markdown = "[Codeskills](https://codeskills.dev)";
const expected = `<Section><Link href="https://codeskills.dev" style={${JSON.stringify(
styles.link
)}}>Codeskills</Link></Section>`;
> This is a block quote.
> It can span multiple lines.
> > This is a nested quote
> > With multiple
> > Lines of code
const rendered = parseMarkdownToReactEmail(markdown);
expect(rendered).toBe(expected);
});
> Block quotes are often used to highlight important information or provide references.`;

it("converts code blocks correctly", () => {
const markdown = '```javascript\nconsole.log("Hello, World!");\n```';
const expected = `<Section><pre style={${JSON.stringify(
styles.codeBlock
)}}><Text>{\`javascript
console.log("Hello, World!");
\`}</Text></pre></Section>`;
const expected = `<Section><Heading as=\"h5\" style={{\"fontWeight\":\"500\",\"paddingTop\":20,\"fontSize\":\"1.25rem\"}}>Header 5</Heading>
const rendered = parseMarkdownToReactEmail(markdown);
expect(rendered).toBe(expected);
});
<Text>An image example:</Text>
<Img src=\"https://example.com/image.jpg\" alt=\"Alt Text\" />
it("converts tables correctly", () => {
const markdown = `
| Header 1 | Header 2 |
| -------- | -------- |
| Cell 1 | Cell 2 |
| Cell 3 | Cell 4 |
`;
const expected =
'<Section><table style={{}}><thead style={{}}><tr style={{"color":"red"}}><th style={{}} align="center">Header 1</th><th style={{}} align="center">Header 2</th></tr></thead><tbody style={{}}><tr style={{"color":"red"}}><td style={{}} align="center">Cell 1</td><td style={{}} align="center">Cell 2</td></tr><tr style={{"color":"red"}}><td style={{}} align="center">Cell 3</td><td style={{}} align="center">Cell 4</td></tr></tbody></table></Section>';
<Heading as=\"h6\" style={{\"fontWeight\":\"500\",\"paddingTop\":20,\"fontSize\":\"1rem\"}}>Header 6</Heading>
const rendered = parseMarkdownToReactEmail(markdown, {
tr: { color: "red" },
});
expect(rendered).toBe(expected);
});
<Text>Some <strong style={{\"fontWeight\":\"bold\"}}>bold text</strong> and <em style={{\"fontStyle\":\"italic\"}}>italic text</em> <em style={{\"fontStyle\":\"italic\"}}>italic text</em>.</Text>
<Text>Code block example:</Text>
<pre style={{\"color\":\"#212529\",\"fontSize\":\"87.5%\",\"display\":\"inline\",\"background\":\" #f8f8f8\",\"fontFamily\":\"SFMono-Regular,Menlo,Monaco,Consolas,monospace\",\"paddingTop\":10,\"paddingRight\":10,\"paddingLeft\":10,\"paddingBottom\":1,\"marginBottom\":20,\"wordWrap\":\"break-word\"}}>
javascript
function greet() {
console.log('Hello!');
}
</pre>
<Text>Here is a block quote example:</Text>
<Text style={{"background":"#f9f9f9","borderLeft":"10px solid #ccc","margin":"1.5em 10px","padding":"1em 10px"}}>
<Text>This is a block quote.</Text>
<Text>It can span multiple lines.</Text>
<Text style={{"background":"#f9f9f9","borderLeft":"10px solid #ccc","margin":"1.5em 10px","padding":"1em 10px"}}>
<Text>This is a nested quote</Text>
<Text>With multiple</Text>
<Text>Lines of code</Text>
</Text>
</Text>
it("converts strikethrough blocks correctly", () => {
const markdown = "~~This is a paragraph.~~";
const expected = `<Section><del style={${JSON.stringify(
styles.strikethrough
)}}>This is a paragraph.</del></Section>`;
<Text style={{"background":"#f9f9f9","borderLeft":"10px solid #ccc","margin":"1.5em 10px","padding":"1em 10px"}}>
<Text>Block quotes are often used to highlight important information or provide references.</Text>
</Text></Section>`;

const rendered = parseMarkdownToReactEmail(markdown);
expect(rendered).toBe(expected);
Expand Down
Loading

0 comments on commit 938b9c8

Please sign in to comment.