基于Frontity正确显示WordPress文章内容
本篇文章介绍如何对 WordPress 的文章内容做兼容性适配,比如文章中的界面元素、样式、链接等做兼容性处理,主要是保证经过 WordPress 内容编辑器(Gutenberg)生成的文章可以正确地显示在 Frontity 的网站界面中。
在 Frontity 应用里能够正确显示 WordPress 内容编辑器中的各种元素的主要工作包括三个部分,一个是 WordPress Gutenberg 主题样式的移植,第二个是 WordPress 中用户自定义的样式移植,第三个是对 WordPress 文章中的一些特定界面元素做兼容性处理。
一、Gutenberg 主题样式移植
这个比较简单,根据你的 Gutenberg 版本到这个网站找对应的 Style.css 和 Theme.css两个文件,然后拷贝到 Frontity 项目的 assets/gutenberg 目录下,并在 Frontity 应用组件的 index.js 中声明一下即可。
sample-frontity-project/packages/frontity-chakra-theme/src/components/index.js
...
import KflyoIcon from "../assets/kflyo.png";
import gutenbergStyle from "../assets/gutenberg/style.css";
import gutenbergTheme from "../assets/gutenberg/theme.css";
import KflyoOne from "../assets/kflyo-one.css";
// Theme is the root React component of our theme. The one we will export
// in roots.
const Theme = ({ state }) => {
// Get information about the current URL.
const data = state.source.get(state.router.link);
const overrides = extendTheme({
fonts: {
heading: "Kelson, system-ui, Helvetica, sans-serif"
},
colors: { ...state.theme.colors }
});
return (
<ChakraProvider theme={{ ...overrides }}>
...
<Global styles={css(gutenbergStyle)} /> {/*Gutenberg 样式*/}
<Global styles={css(gutenbergTheme)} /> {/*Gutenberg 主题样式*/}
<Global styles={css(KflyoOne)} /> {/*用户自定义样式*/}
</ChakraProvider>
);
};
export default connect(Theme);
更详细的内容,这有一篇文章可以参考。
二、WordPress 用户自定义样式移植
这个跟上面的做法一样,把用户自定义样式拷贝到 Frontity 相应的目录下,然后声明一下即可。
三、WordPress 文章内容元素兼容性适配
这个要用到 Frontity 的 html2react 组件,作用是把 html 元素转换成 react 组件,然后以组件的方式处理 html 元素。
htmltoreact 组件的一个重要的功能是 processor,定义 html 界面元素对应的 React 组件,定义好后,就可以按照 React 的方式处理界面元素了。
比如文章中代码的语法显示部分,对 pre 标签的处理:
sample-frontity-project/packages/frontity-chakra-theme/src/components/styles/ processors.js
import React from "react";
import { Alert, Text, Box, Heading, others } from "@chakra-ui/react";
import Link from "../link";
import PreCode from "../precode";
import { getPostData, formatPostData } from "../helpers";
import post from "../post/post";
/**
*
* @param {React.ElementType} tag
* @param {{props: (nodeProps: Object) => Object, component: React.ComponentType<any>}} options
*/
function makeProcessor(tag, options) {
return {
name: tag,
test: ({ node }) => node.component === tag,
processor: ({ node, state }) => {
var isGalleryOrVideo = null;
if(options.component==PostLink) {
const postData = getPostData(state);
const post = formatPostData(state, postData);
isGalleryOrVideo = (post.format=="gallery" || post.format=="image")?{'data-lightbox': post.format}:(post.format=="video" || node.props.href.endsWith(".gif"))?{'data-videobox': "video"}:null;
}
node.component = options.component || node.tag;
node.props = { ...options.props({ node }), ...node.props, ...isGalleryOrVideo };
return node;
},
// allow for overriding this processors
priority: 20
};
}
...
const pre = makeProcessor("pre", {
props: () => {
return {
className: "wp-block-code prettyprint",
};
},
component: PreCode
});
const processors = [blockquote, paragraph, figcaption, h3, a, pre];
export default processors;
sample-frontity-project/packages/frontity-chakra-theme/src/components/precode.js
import { connect } from "frontity";
import React from "react";
const PreCode = ({
className,
children,
...props
}) => {console.log(className)
return (
<pre className="wp-block-code prettyprint">
{children}
</pre>
);
};
export default connect(PreCode)
最后,用户在 WordPress 中开发好的 JavaScript 和 Css 代码可以声明并使用。
sample-frontity-project/packages/frontity-chakra-theme/src/components/index.js
// Theme is the root React component of our theme. The one we will export
// in roots.
const Theme = ({ state }) => {
// Get information about the current URL.
const data = state.source.get(state.router.link);
const overrides = extendTheme({
fonts: {
heading: "Kelson, system-ui, Helvetica, sans-serif"
},
colors: { ...state.theme.colors }
});
return (
<ChakraProvider theme={{ ...overrides }}>
<FontFace />
{/* Add some metatags to the <head> of the HTML. */}
<Title />
<Head>
<meta name="description" content={state.frontity.description} />
<html lang="zh-CN" />
<link rel="icon" href={KflyoIcon} sizes="32x32"></link>
<script src="https://cdn.jsdelivr.net/gh/google/code-prettify@master/loader/run_prettify.js"></script>
<script type="text/javascript" src="https://www.kflyo.com/wp-includes/js/jquery/jquery.js?ver=1.12.4"></script>
<script type="text/javascript" src="https://www.kflyo.com/wp-includes/js/jquery/jquery-migrate.min.js?ver=1.4.1"></script>
<script type="text/javascript" src="https://www.kflyo.com/wp-content/plugins/kflyo-utility-tools/js/kflyo.js?ver=1.1"></script>
<link rel="stylesheet" id="kflyo-css" href="https://www.kflyo.com/wp-content/plugins/kflyo-utility-tools/css/kflyo.css?ver=1.1" type="text/css" media="all"></link>
</Head>
{/* Add the header of the site. */}
<Header />
{/* Add the main section. It renders a different component depending
on the type of URL we are in. */}
<Box
as="main"
mt={{ base: "40px", md: "70px" }}
minH="calc(100vh - 320px)"
>
<Switch>
<Loading when={data.isFetching} />
<SearchResults when={data.isSearch} />
<Archive when={data.isArchive} />
<Post when={data.isPostType} />
<Page404 when={data.is404} />
</Switch>
</Box>
<Footer />
<Global styles={css(gutenbergStyle)} />
<Global styles={css(gutenbergTheme)} />
<Global styles={css(KflyoOne)} />
</ChakraProvider>
);
};
export default connect(Theme);