WIP: updated HTMLReactParserOptions replace function, from complex if else to handler pattern
This commit is contained in:
parent
a607a4528e
commit
a1cba242e9
2
.gitignore
vendored
2
.gitignore
vendored
@ -5,6 +5,8 @@
|
|||||||
/.pnp
|
/.pnp
|
||||||
.pnp.js
|
.pnp.js
|
||||||
|
|
||||||
|
/.local/
|
||||||
|
|
||||||
# testing
|
# testing
|
||||||
/coverage
|
/coverage
|
||||||
|
|
||||||
|
|||||||
109
app/post/[slug]/nodeHandler.tsx
Normal file
109
app/post/[slug]/nodeHandler.tsx
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
import {ReactElement} from "react";
|
||||||
|
import {domToReact, Element} from "html-react-parser";
|
||||||
|
import {nunito_sans, raleway} from "@/app/fonts";
|
||||||
|
import {Code} from "bright";
|
||||||
|
import {mark} from "@/bright-extension/mark";
|
||||||
|
|
||||||
|
export type nodeHandlerResult = {match :boolean, element? :ReactElement}
|
||||||
|
export type nodeHandler = (node :Element) => nodeHandlerResult
|
||||||
|
|
||||||
|
function h1(node: Element): nodeHandlerResult {
|
||||||
|
if (node.name === "h1") {
|
||||||
|
if (node.attribs.class === "title") {
|
||||||
|
return {
|
||||||
|
match: true,
|
||||||
|
element: (
|
||||||
|
<h1 className={`${raleway.className} mx-auto w-224 text-4xl`}>
|
||||||
|
{domToReact(node.children)}
|
||||||
|
</h1>
|
||||||
|
),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
match: true,
|
||||||
|
element: (
|
||||||
|
<h1 className={`${raleway.className} mx-auto w-224 text-3xl`}>
|
||||||
|
{domToReact(node.children)}
|
||||||
|
</h1>
|
||||||
|
),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return { match: false};
|
||||||
|
}
|
||||||
|
|
||||||
|
function h2(node: Element): nodeHandlerResult {
|
||||||
|
if (node.name === "h2") {
|
||||||
|
return {
|
||||||
|
match: true,
|
||||||
|
element: (
|
||||||
|
<h1 className={`${raleway.className} mx-auto w-224 text-2xl`}>
|
||||||
|
{domToReact(node.children)}
|
||||||
|
</h1>
|
||||||
|
)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {match: false};
|
||||||
|
}
|
||||||
|
|
||||||
|
function h3(node: Element): nodeHandlerResult {
|
||||||
|
if (node.name === "h3") {
|
||||||
|
return {
|
||||||
|
match: true,
|
||||||
|
element: (
|
||||||
|
<h1 className={`${raleway.className} mx-auto w-224 text-xl`}>
|
||||||
|
{domToReact(node.children)}
|
||||||
|
</h1>
|
||||||
|
)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {match: false};
|
||||||
|
}
|
||||||
|
|
||||||
|
function code(node: Element): nodeHandlerResult {
|
||||||
|
if (node.name === "code") {
|
||||||
|
let linenumber = false;
|
||||||
|
if ("class" in node.attribs) {
|
||||||
|
const classes = node.attribs.class.split(" ");
|
||||||
|
if (classes.includes("linenumber")) {
|
||||||
|
linenumber = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
match: true,
|
||||||
|
element: (
|
||||||
|
<div className={`w-224 mx-auto`}>
|
||||||
|
<Code
|
||||||
|
lang={`${node.attribs.lang}`}
|
||||||
|
lineNumbers={linenumber}
|
||||||
|
extensions={[mark]}
|
||||||
|
>
|
||||||
|
{domToReact(node.children)}
|
||||||
|
</Code>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {match: false};
|
||||||
|
}
|
||||||
|
|
||||||
|
function p(node: Element): nodeHandlerResult {
|
||||||
|
if (node.name === "p") {
|
||||||
|
if (node.attribs.class === "paragraph") {
|
||||||
|
return {
|
||||||
|
match: true,
|
||||||
|
element: (
|
||||||
|
<h1 className={`${nunito_sans.className} mx-auto w-224`}>
|
||||||
|
{domToReact(node.children)}
|
||||||
|
</h1>
|
||||||
|
)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {match: false};
|
||||||
|
}
|
||||||
|
|
||||||
|
export const handlers: nodeHandler[] = [h1, h2, h3, code, p];
|
||||||
@ -1,69 +1,21 @@
|
|||||||
import { getPost } from "@/backend/post";
|
import { getPost } from "@/backend/post";
|
||||||
import DOMPurify from "dompurify";
|
import DOMPurify from "dompurify";
|
||||||
import { JSDOM } from "jsdom";
|
import { JSDOM } from "jsdom";
|
||||||
import { nunito_sans, raleway } from "@/app/fonts";
|
|
||||||
import parse, {
|
import parse, {
|
||||||
domToReact,
|
|
||||||
Element,
|
Element,
|
||||||
|
// domToReact,
|
||||||
HTMLReactParserOptions,
|
HTMLReactParserOptions,
|
||||||
} from "html-react-parser";
|
} from "html-react-parser";
|
||||||
import { DummyPostSlug, DummyPostString } from "@/components/dummyPost";
|
import { DummyPostSlug, DummyPostString } from "@/components/dummyPost";
|
||||||
import { Code } from "bright";
|
import { handlers } from "@/app/post/[slug]/nodeHandler";
|
||||||
import { mark } from "@/bright-extension/mark";
|
|
||||||
|
|
||||||
const options: HTMLReactParserOptions = {
|
const options: HTMLReactParserOptions = {
|
||||||
replace: (domNode) => {
|
replace: (domNode) => {
|
||||||
if (domNode instanceof Element && domNode.attribs) {
|
for (let handler of handlers) {
|
||||||
// console.log(domNode.attribs)
|
if (domNode instanceof Element && domNode.attribs) {
|
||||||
if (domNode.name === "h1") {
|
let result = handler(domNode)
|
||||||
if (domNode.attribs.class === "title") {
|
if (result.match && typeof result.element !== 'undefined') {
|
||||||
return (
|
return result.element
|
||||||
<h1 className={`${raleway.className} mx-auto w-224 text-4xl`}>
|
|
||||||
{domToReact(domNode.children)}
|
|
||||||
</h1>
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return (
|
|
||||||
<h1 className={`${raleway.className} mx-auto w-224 text-3xl`}>
|
|
||||||
{domToReact(domNode.children)}
|
|
||||||
</h1>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else if (domNode.name === "h2") {
|
|
||||||
return (
|
|
||||||
<h1 className={`${raleway.className} mx-auto w-224 text-2xl`}>
|
|
||||||
{domToReact(domNode.children)}
|
|
||||||
</h1>
|
|
||||||
);
|
|
||||||
} else if (domNode.name === "h3") {
|
|
||||||
return (
|
|
||||||
<h1 className={`${raleway.className} mx-auto w-224 text-xl`}>
|
|
||||||
{domToReact(domNode.children)}
|
|
||||||
</h1>
|
|
||||||
);
|
|
||||||
} else if (domNode.name === "code") {
|
|
||||||
let linenumber = false
|
|
||||||
if ('class' in domNode.attribs) {
|
|
||||||
const classes = domNode.attribs.class.split(" ");
|
|
||||||
if (classes.includes('linenumber')) {
|
|
||||||
linenumber = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<div className={`w-224 mx-auto`}>
|
|
||||||
<Code lang={`${domNode.attribs.lang}`} lineNumbers={linenumber} extensions={[mark]}>
|
|
||||||
{domToReact(domNode.children)}
|
|
||||||
</Code>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
} else if (domNode.name === "p") {
|
|
||||||
// console.log(domNode.children)
|
|
||||||
if (domNode.attribs.class === "paragraph") {
|
|
||||||
return (
|
|
||||||
<h1 className={`${nunito_sans.className} mx-auto w-224`}>
|
|
||||||
{domToReact(domNode.children)}
|
|
||||||
</h1>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -71,7 +23,7 @@ const options: HTMLReactParserOptions = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default async function Post({ params }: { params: { slug: string } }) {
|
export default async function Post({ params }: { params: { slug: string } }) {
|
||||||
let content = "";
|
let content;
|
||||||
|
|
||||||
const dummySlug = await DummyPostSlug();
|
const dummySlug = await DummyPostSlug();
|
||||||
if (dummySlug === params.slug) {
|
if (dummySlug === params.slug) {
|
||||||
|
|||||||
@ -1,11 +1,25 @@
|
|||||||
import mysql, { PoolOptions } from "mysql2";
|
import mysql, { PoolOptions } from "mysql2";
|
||||||
|
import * as fs from 'fs';
|
||||||
|
import * as appEnv from "./env";
|
||||||
|
|
||||||
|
if (typeof process.env.MYSQL_SSL_CA === 'undefined') {
|
||||||
|
throw new Error("missing MYSQL_SSL_CA")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof process.env.MYSQL_SSL_KEY === 'undefined') {
|
||||||
|
throw new Error("missing MYSQL_SSL_KEY")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof process.env.MYSQL_SSL_CERT === 'undefined') {
|
||||||
|
throw new Error("missing MYSQL_SSL_CERT")
|
||||||
|
}
|
||||||
|
|
||||||
const access: PoolOptions = {
|
const access: PoolOptions = {
|
||||||
host: process.env.MYSQL_HOST,
|
host: appEnv.getMysqlHost(),
|
||||||
port: 'MYSQL_PORT' in process.env && typeof process.env.MYSQL_PORT === 'string' ? parseInt(process.env.MYSQL_PORT) : 3306,
|
port: appEnv.getMysqlPort(),
|
||||||
user: process.env.MYSQL_USER,
|
user: appEnv.getMysqlUser(),
|
||||||
password: process.env.MYSQL_PASSWORD,
|
password: appEnv.getMysqlPassword(),
|
||||||
database: 'MYSQL_DATABASE' in process.env ? process.env.MYSQL_DATABASE : 'blog',
|
database: appEnv.getMysqlDatabase(),
|
||||||
waitForConnections: true,
|
waitForConnections: true,
|
||||||
connectionLimit: 10,
|
connectionLimit: 10,
|
||||||
maxIdle: 10,
|
maxIdle: 10,
|
||||||
@ -13,6 +27,11 @@ const access: PoolOptions = {
|
|||||||
queueLimit: 0,
|
queueLimit: 0,
|
||||||
enableKeepAlive: true,
|
enableKeepAlive: true,
|
||||||
keepAliveInitialDelay: 0,
|
keepAliveInitialDelay: 0,
|
||||||
|
ssl: {
|
||||||
|
ca: fs.readFileSync(appEnv.getMysqlSslCaFile()),
|
||||||
|
key: fs.readFileSync(appEnv.getMysqlSslKeyFile()),
|
||||||
|
cert: fs.readFileSync(appEnv.getMysqlSslCertFile())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const pool = mysql.createPool(access)
|
export const pool = mysql.createPool(access)
|
||||||
|
|||||||
63
backend/env.ts
Normal file
63
backend/env.ts
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
export function getMysqlHost(): string {
|
||||||
|
if (typeof process.env.MYSQL_HOST === 'undefined') {
|
||||||
|
throw new Error("missing env MYSQL_HOST")
|
||||||
|
}
|
||||||
|
|
||||||
|
return process.env.MYSQL_HOST
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getMysqlPort(): number {
|
||||||
|
if (typeof process.env.MYSQL_PORT === 'undefined') {
|
||||||
|
throw new Error("missing env MYSQL_PORT")
|
||||||
|
}
|
||||||
|
|
||||||
|
return parseInt(process.env.MYSQL_PORT)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getMysqlUser(): string {
|
||||||
|
if (typeof process.env.MYSQL_USER === 'undefined') {
|
||||||
|
throw new Error("missing env MYSQL_USER")
|
||||||
|
}
|
||||||
|
|
||||||
|
return process.env.MYSQL_USER
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getMysqlPassword(): string {
|
||||||
|
if (typeof process.env.MYSQL_PASSWORD === 'undefined') {
|
||||||
|
throw new Error("missing env MYSQL_PASSWORD")
|
||||||
|
}
|
||||||
|
|
||||||
|
return process.env.MYSQL_PASSWORD
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getMysqlDatabase(): string {
|
||||||
|
if (typeof process.env.MYSQL_DATABASE === 'undefined') {
|
||||||
|
throw new Error("missing env MYSQL_DATABASE")
|
||||||
|
}
|
||||||
|
|
||||||
|
return process.env.MYSQL_DATABASE
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getMysqlSslCaFile(): string {
|
||||||
|
if (typeof process.env.MYSQL_SSL_CA === 'undefined') {
|
||||||
|
throw new Error("missing env MYSQL_SSL_CA")
|
||||||
|
}
|
||||||
|
|
||||||
|
return process.env.MYSQL_SSL_CA
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getMysqlSslCertFile(): string {
|
||||||
|
if (typeof process.env.MYSQL_SSL_CERT === 'undefined') {
|
||||||
|
throw new Error("missing env MYSQL_SSL_CERT")
|
||||||
|
}
|
||||||
|
|
||||||
|
return process.env.MYSQL_SSL_CERT
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getMysqlSslKeyFile(): string {
|
||||||
|
if (typeof process.env.MYSQL_SSL_KEY === 'undefined') {
|
||||||
|
throw new Error("missing env MYSQL_SSL_KEY")
|
||||||
|
}
|
||||||
|
|
||||||
|
return process.env.MYSQL_SSL_KEY
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user