-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: youtube and twitter embeds for articles (#500)
- Loading branch information
1 parent
4e67f1c
commit 1140b1f
Showing
11 changed files
with
341 additions
and
178 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
Large diffs are not rendered by default.
Oops, something went wrong.
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
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
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,13 @@ | ||
import { type Node } from "unist"; | ||
|
||
export interface NodeWithChildren extends Node { | ||
children: NodeWithChildren[]; | ||
alt?: string; | ||
url?: string; | ||
value?: string; | ||
} | ||
|
||
export interface NodeOptionalChildren extends Omit<Node, "children"> { | ||
children?: NodeWithChildren[]; | ||
value?: string; | ||
} |
82 changes: 82 additions & 0 deletions
82
resources/js/Utils/Remark/remarkTwitterEmbedPlugin.test.ts
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,82 @@ | ||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */ | ||
import { type NodeWithChildren } from "./remarkPlugins.contract"; | ||
import { remarkTwitterEmbedPlugin } from "./remarkTwitterEmbedPlugin"; | ||
|
||
describe("remarkTwitterEmbedPlugin", () => { | ||
it("transforms Twitter links into embeds", () => { | ||
const tree: NodeWithChildren = { | ||
type: "root", | ||
children: [ | ||
{ | ||
type: "paragraph", | ||
children: [ | ||
{ | ||
type: "image", | ||
url: "twitter:bobconfer/status/1575764493795479552", | ||
children: [], | ||
}, | ||
], | ||
}, | ||
], | ||
}; | ||
|
||
remarkTwitterEmbedPlugin()(tree); | ||
|
||
expect(tree.children[0].type).toBe("html"); | ||
expect(tree.children[0].value).toContain("twitter.com/bobconfer/status/1575764493795479552"); | ||
expect(tree.children[0].value).toContain("twitter-tweet"); | ||
}); | ||
|
||
it("does not transform non-Twitter links", () => { | ||
const tree: NodeWithChildren = { | ||
type: "root", | ||
children: [ | ||
{ | ||
type: "paragraph", | ||
children: [ | ||
{ | ||
type: "image", | ||
url: "https://example.com/image.jpg", | ||
children: [], | ||
}, | ||
], | ||
}, | ||
], | ||
}; | ||
|
||
const originalTree = JSON.parse(JSON.stringify(tree)); | ||
|
||
remarkTwitterEmbedPlugin()(tree); | ||
|
||
expect(tree).toEqual(originalTree); | ||
}); | ||
|
||
it("does not transform Twitter links if not the only child in a paragraph", () => { | ||
const tree: NodeWithChildren = { | ||
type: "root", | ||
children: [ | ||
{ | ||
type: "paragraph", | ||
children: [ | ||
{ | ||
type: "text", | ||
value: "Random text", | ||
children: [], | ||
}, | ||
{ | ||
type: "image", | ||
url: "twitter:bobconfer/status/1575764493795479552", | ||
children: [], | ||
}, | ||
], | ||
}, | ||
], | ||
}; | ||
|
||
const originalTree = JSON.parse(JSON.stringify(tree)); | ||
|
||
remarkTwitterEmbedPlugin()(tree); | ||
|
||
expect(tree).toEqual(originalTree); | ||
}); | ||
}); |
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,23 @@ | ||
/* eslint-disable @typescript-eslint/no-non-null-assertion */ | ||
import { visit } from "unist-util-visit"; | ||
import { type NodeWithChildren } from "./remarkPlugins.contract"; | ||
|
||
const transformTwitterNodes = (tree: NodeWithChildren): void => { | ||
visit(tree, "paragraph", (node: NodeWithChildren, index, parent) => { | ||
if (node.children.length === 1 && node.children[0].type === "image") { | ||
const imageNode = node.children[0]; | ||
|
||
if (typeof imageNode.url === "string" && imageNode.url.startsWith("twitter:")) { | ||
const twitterPath = imageNode.url.replace("twitter:", ""); | ||
|
||
parent!.children.splice(index!, 1, { | ||
type: "html", | ||
value: `<div class="twitter-embed-wrapper"><blockquote class="twitter-tweet"><a href="https://twitter.com/${twitterPath}"></a></blockquote></div><div class="twitter-embed-wrapper twitter-embed-wrapper-dark"><blockquote class="twitter-tweet" data-theme="dark"><a href="https://twitter.com/${twitterPath}"></a></blockquote></div>`, | ||
children: [], | ||
}); | ||
} | ||
} | ||
}); | ||
}; | ||
|
||
export const remarkTwitterEmbedPlugin = (): ((tree: NodeWithChildren) => void) => transformTwitterNodes; |
54 changes: 54 additions & 0 deletions
54
resources/js/Utils/Remark/remarkYoutubeEmbedPlugin.test.ts
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,54 @@ | ||
import { type NodeWithChildren } from "./remarkPlugins.contract"; | ||
import { remarkYoutubeEmbedPlugin } from "./remarkYoutubeEmbedPlugin"; | ||
|
||
describe("remarkYoutubeEmbedPlugin", () => { | ||
it("transforms YouTube links into iframe embeds", () => { | ||
const tree: NodeWithChildren = { | ||
type: "root", | ||
children: [ | ||
{ | ||
type: "paragraph", | ||
children: [ | ||
{ | ||
type: "image", | ||
url: "youtube:bH1lHCirCGI", | ||
children: [], | ||
}, | ||
], | ||
}, | ||
], | ||
}; | ||
|
||
remarkYoutubeEmbedPlugin()(tree); | ||
|
||
expect(tree.children[0].children[0].type).toBe("html"); | ||
expect(tree.children[0].children[0].value).toBe( | ||
'<iframe src="https://www.youtube.com/embed/bH1lHCirCGI" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>', | ||
); | ||
}); | ||
|
||
it("does not transform non-YouTube links", () => { | ||
const tree: NodeWithChildren = { | ||
type: "root", | ||
children: [ | ||
{ | ||
type: "paragraph", | ||
children: [ | ||
{ | ||
type: "image", | ||
url: "https://example.com/image.jpg", | ||
children: [], | ||
}, | ||
], | ||
}, | ||
], | ||
}; | ||
|
||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment | ||
const originalTree = JSON.parse(JSON.stringify(tree)); | ||
|
||
remarkYoutubeEmbedPlugin()(tree); | ||
|
||
expect(tree).toEqual(originalTree); | ||
}); | ||
}); |
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,16 @@ | ||
import { visit } from "unist-util-visit"; | ||
import { type NodeWithChildren } from "./remarkPlugins.contract"; | ||
|
||
const transformYouTubeNodes = (tree: NodeWithChildren): void => { | ||
visit(tree, "image", (node: NodeWithChildren) => { | ||
if (typeof node.url === "string" && node.url.startsWith("youtube:")) { | ||
const videoId = node.url.replace("youtube:", ""); | ||
|
||
// Convert the node to an HTML node with the iframe embed | ||
node.type = "html"; | ||
node.value = `<iframe src="https://www.youtube.com/embed/${videoId}" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>`; | ||
} | ||
}); | ||
}; | ||
|
||
export const remarkYoutubeEmbedPlugin = (): ((tree: NodeWithChildren) => void) => transformYouTubeNodes; |