mirror of
https://github.com/nature-of-code/noc-book-2
synced 2024-09-29 05:36:56 +02:00
[feature] support video link with headings
This commit is contained in:
parent
78efa02ad0
commit
45717816a2
3 changed files with 51 additions and 6 deletions
|
@ -11,9 +11,13 @@ import { toString } from 'hast-util-to-string';
|
|||
|
||||
import { rehypeCodesplit } from './codesplit.mjs';
|
||||
|
||||
function isHeading(node) {
|
||||
return node.type === 'element' && /^h[1-6]$/i.test(node.tagName);
|
||||
}
|
||||
|
||||
export function parseContent(html) {
|
||||
const replaceMedia = () => (tree) => {
|
||||
visit(tree, { tagName: 'div' }, (node) => {
|
||||
visit(tree, { tagName: 'div' }, (node, index, parent) => {
|
||||
if (
|
||||
node.properties.className &&
|
||||
Array.isArray(node.properties.className) &&
|
||||
|
@ -44,6 +48,19 @@ export function parseContent(html) {
|
|||
node.tagName = 'embed-example';
|
||||
}
|
||||
|
||||
if (
|
||||
node.properties.dataType === 'video-link' &&
|
||||
node.properties.dataTitle &&
|
||||
index > 2 &&
|
||||
isHeading(parent.children[index - 2])
|
||||
) {
|
||||
node.tagName = 'video-link';
|
||||
|
||||
// move the video-link node inside the last adjacent heading
|
||||
parent.children[index - 2].children.push(node);
|
||||
parent.children.splice(index, 1);
|
||||
}
|
||||
|
||||
if (
|
||||
node.properties.dataType === 'note' ||
|
||||
node.properties.dataType === 'exercise' ||
|
||||
|
@ -151,11 +168,6 @@ export function parseContent(html) {
|
|||
const description = paragraphs.join(' ').trim().substring(0, 150);
|
||||
|
||||
const transformedAst = unified()
|
||||
.use(replaceMedia)
|
||||
.use(externalLinkInNewTab)
|
||||
.use(rehypeCodesplit)
|
||||
.use(rehypeHighlight)
|
||||
.use(rehypeSlug)
|
||||
.use(rehypeAutolinkHeadings, {
|
||||
behavior: 'wrap',
|
||||
test: ['h2', 'h3'],
|
||||
|
@ -163,6 +175,11 @@ export function parseContent(html) {
|
|||
class: 'heading-link',
|
||||
},
|
||||
})
|
||||
.use(replaceMedia)
|
||||
.use(externalLinkInNewTab)
|
||||
.use(rehypeCodesplit)
|
||||
.use(rehypeHighlight)
|
||||
.use(rehypeSlug)
|
||||
.use(rehypeKatex)
|
||||
.runSync(ast);
|
||||
|
||||
|
|
26
src/components/VideoLink.js
Normal file
26
src/components/VideoLink.js
Normal file
|
@ -0,0 +1,26 @@
|
|||
import React from 'react';
|
||||
import { FaYoutube } from 'react-icons/fa';
|
||||
|
||||
const VideoLink = (props) => {
|
||||
return (
|
||||
<div className="ml-6 inline-block">
|
||||
<a
|
||||
className="group relative flex items-center gap-2 text-base text-noc-400 no-underline"
|
||||
href={props['href']}
|
||||
>
|
||||
<FaYoutube />
|
||||
{props['data-title']}
|
||||
|
||||
{props.children && (
|
||||
<div className="not-prose absolute top-0 hidden w-80 pt-10 group-hover:block">
|
||||
<div className="rounded-lg bg-noc-500 bg-opacity-50 p-4">
|
||||
{props.children}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</a>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default VideoLink;
|
|
@ -8,6 +8,7 @@ import SideNavLayout from './SideNavLayout';
|
|||
import PrevNextButtons from '../components/PrevNextButtons';
|
||||
import Image from '../components/Image';
|
||||
import Example from '../components/Example';
|
||||
import VideoLink from '../components/VideoLink';
|
||||
|
||||
const renderAst = ({ ast, images }) => {
|
||||
visit(ast, { tagName: 'img' }, (node) => {
|
||||
|
@ -29,6 +30,7 @@ const renderAst = ({ ast, images }) => {
|
|||
components: {
|
||||
'gatsby-image': Image,
|
||||
'embed-example': Example,
|
||||
'video-link': VideoLink,
|
||||
},
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in a new issue