From ffe6e1ee8a3bf6e9d73f501bbd7b956d54e761bd Mon Sep 17 00:00:00 2001 From: 2nthony Date: Fri, 5 Jan 2024 17:15:35 +0800 Subject: [PATCH] fix: html ssr warning (#64) * fix: html ssr warning BREAKING CHANGE: plugin `collectCss` removed * docs: update --- README.md | 3 +- package.json | 2 +- src/HtmlPreviewer.tsx | 28 +- src/components/Html.tsx | 201 -------------- src/components/Prism.ts | 148 ---------- src/plugins/index.ts | 2 - src/plugins/maxLines.ts | 20 -- src/plugins/minHeight.ts | 19 -- src/plugins/renderMentionIdentityUser.ts | 11 +- src/styles.css | 331 +++++++++++++++++++++++ src/types.ts | 12 - 11 files changed, 348 insertions(+), 429 deletions(-) delete mode 100644 src/components/Html.tsx delete mode 100644 src/components/Prism.ts delete mode 100644 src/plugins/maxLines.ts delete mode 100644 src/plugins/minHeight.ts create mode 100644 src/styles.css diff --git a/README.md b/README.md index 40b1cff..6579864 100644 --- a/README.md +++ b/README.md @@ -8,8 +8,9 @@ Preview markdown/html. yarn add @osn/previewer ``` -```ts +```jsx import { HtmlPreviewer, MarkdownPreviewer, renderMentionIdentityUserPlugin } from "@osn/previewer" +import "@osn/previewer/styles.css" function MentionIdentityUser({ address, network }) { return {address} diff --git a/package.json b/package.json index 67214a8..344e36d 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "scripts": { "dev": "vite", "build:demo": "tsc && vite build", - "build": "tsup --dts --format esm,cjs --clean --inject ./react-import.js ./src", + "build": "tsup --dts --format esm,cjs --clean --inject ./react-import.js ./src/index.ts && cp ./src/styles.css ./dist", "prepublishOnly": "npm run build" }, "files": [ diff --git a/src/HtmlPreviewer.tsx b/src/HtmlPreviewer.tsx index 1cd2850..436ed93 100644 --- a/src/HtmlPreviewer.tsx +++ b/src/HtmlPreviewer.tsx @@ -1,9 +1,7 @@ import { useEffect, useRef, useState } from "react"; -import { Html } from "./components/Html"; -import type { HtmlProps, PreviewerProps } from "./types"; -import { css } from "styled-components"; +import type { PreviewerProps } from "./types"; import { applyPlugins } from "./shared"; -import { minHeightPlugin, sanitizeHtmlPlugin, maxLinesPlugin } from "./plugins"; +import { sanitizeHtmlPlugin } from "./plugins"; export function HtmlPreviewer(props: PreviewerProps) { const { @@ -15,15 +13,7 @@ export function HtmlPreviewer(props: PreviewerProps) { maxLines, } = props; - const resolvedPlugins = [ - minHeightPlugin(minHeight), - maxLinesPlugin(maxLines), - ...plugins, - sanitizeHtmlPlugin(allowedTags), - ]; - - const extraCss: HtmlProps["extraCss"] = []; - applyPlugins(resolvedPlugins, "collectCss", css, (str) => extraCss.push(str)); + const resolvedPlugins = [...plugins, sanitizeHtmlPlugin(allowedTags)]; const ref = useRef(null); const [html, setHtml] = useState(content); @@ -36,9 +26,17 @@ export function HtmlPreviewer(props: PreviewerProps) { return (
-
diff --git a/src/components/Html.tsx b/src/components/Html.tsx deleted file mode 100644 index a5459a9..0000000 --- a/src/components/Html.tsx +++ /dev/null @@ -1,201 +0,0 @@ -import { forwardRef } from "react"; -import styled, { css } from "../styled"; -import type { HtmlProps } from "../types"; -import { PrismCss } from "./Prism"; - -type StyledHtmlProps = HtmlProps & { - $extraCss: HtmlProps["extraCss"]; -}; - -const no_scroll_bar = css` - -ms-overflow-style: none; - scrollbar-width: none; - - ::-webkit-scrollbar { - display: none; - } -`; - -const Wrapper = styled.div` - font-style: normal; - font-weight: 400; - font-size: 14px; - line-height: 24px; - color: #1e2134; - - &.markdown-body, - &.html-body { - word-break: normal; - - h1, - h2, - h3, - h4, - h5, - h6 { - font-weight: 600; - - margin-top: 24px; - margin-bottom: 16px; - - :first-child { - margin-top: 0; - } - :last-child { - margin-bottom: 0; - } - - & b, - & strong { - font-weight: inherit; - } - } - - h1 { - line-height: 28px; - font-size: 20px; - } - - h2 { - line-height: 24px; - font-size: 18px; - } - - h3 { - line-height: 24px; - font-size: 16px; - } - - h4 { - line-height: 24px; - font-size: 14px; - } - - p { - word-break: break-word; - line-height: 24px !important; - } - - ol, - ul { - padding-left: 1.25em; - } - - ul { - list-style-type: disc; - } - - blockquote { - margin: 0; - padding-left: 0.75em; - border-left: 4px solid #eee; - } - - pre { - ${no_scroll_bar}; - - * { - font-family: i-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, - Liberation Mono, monospace !important; - } - - margin: 8px 0; - padding: 0 8px; - background-color: #f0f3f8; - border-radius: 4px; - white-space: pre-wrap !important; - overflow-x: scroll; - - > code { - padding: 0 !important; - background: transparent !important; - white-space: pre-wrap !important; - display: inline; - - span.identifier { - white-space: nowrap !important; - } - } - } - - code { - font-family: i-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, - Liberation Mono, monospace !important; - padding: 2px 8px; - background-color: #f0f3f8; - border-radius: 4px; - } - - a { - color: #1f70c7; - cursor: pointer; - text-decoration: none; - } - - img { - max-width: 100%; - } - - p a::selection { - background-color: transparent !important; - color: inherit; - } - - th, - td { - border: 1px solid #e2e8f0; - } - - table { - margin: 8px 0; - border-collapse: collapse; - max-width: 100%; - overflow: auto; - display: block; - } - - th { - padding: 10px 16px; - background-color: #f0f3f8; - font-weight: bold; - color: #1e2134; - min-width: 100px; - } - - td { - padding: 10px 16px; - color: #1e2134; - } - - tbody tr:nth-child(even) { - background-color: #fbfcfe; - } - - hr { - background-color: #e2e8f0; - height: 1px; - border: none; - margin: 16px 0; - } - - ${PrismCss}; - - /* NOTE: forced remove token background */ - code[class*="language-"], - pre[class*="language-"] { - .token { - background: transparent; - } - } - } - - ${(p) => p?.$extraCss?.map((s) => s)} -`; - -export const Html = forwardRef((props: any = {}, ref) => { - return ( - - {props.children} - - ); -}); diff --git a/src/components/Prism.ts b/src/components/Prism.ts deleted file mode 100644 index 770529a..0000000 --- a/src/components/Prism.ts +++ /dev/null @@ -1,148 +0,0 @@ -import { css } from "../styled"; - -export const PrismCss = css` - /** - * prism.js default theme for JavaScript, CSS and HTML - * Based on dabblet (http://dabblet.com) - * @author Lea Verou - */ - - code[class*="language-"], - pre[class*="language-"] { - color: black; - background: none; - text-shadow: 0 1px white; - font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; - font-size: 1em; - text-align: left; - white-space: pre; - word-spacing: normal; - word-break: normal; - word-wrap: normal; - line-height: 1.5; - - -moz-tab-size: 4; - -o-tab-size: 4; - tab-size: 4; - - -webkit-hyphens: none; - -moz-hyphens: none; - -ms-hyphens: none; - hyphens: none; - } - - pre[class*="language-"]::-moz-selection, - pre[class*="language-"] ::-moz-selection, - code[class*="language-"]::-moz-selection, - code[class*="language-"] ::-moz-selection { - text-shadow: none; - background: #b3d4fc; - } - - pre[class*="language-"]::selection, - pre[class*="language-"] ::selection, - code[class*="language-"]::selection, - code[class*="language-"] ::selection { - text-shadow: none; - background: #b3d4fc; - } - - @media print { - code[class*="language-"], - pre[class*="language-"] { - text-shadow: none; - } - } - - /* Code blocks */ - pre[class*="language-"] { - padding: 1em; - margin: 0.5em 0; - overflow: auto; - } - - :not(pre) > code[class*="language-"], - pre[class*="language-"] { - background: #f5f2f0; - } - - /* Inline code */ - :not(pre) > code[class*="language-"] { - padding: 0.1em; - border-radius: 0.3em; - white-space: normal; - } - - .token.comment, - .token.prolog, - .token.doctype, - .token.cdata { - color: slategray; - } - - .token.punctuation { - color: #999; - } - - .token.namespace { - opacity: 0.7; - } - - .token.property, - .token.tag, - .token.boolean, - .token.number, - .token.constant, - .token.symbol, - .token.deleted { - color: #905; - } - - .token.selector, - .token.attr-name, - .token.string, - .token.char, - .token.builtin, - .token.inserted { - color: #690; - } - - .token.operator, - .token.entity, - .token.url, - .language-css .token.string, - .style .token.string { - color: #9a6e3a; - /* This background color was intended by the author of this theme. */ - background: hsla(0, 0%, 100%, 0.5); - } - - .token.atrule, - .token.attr-value, - .token.keyword { - color: #07a; - } - - .token.function, - .token.class-name { - color: #dd4a68; - } - - .token.regex, - .token.important, - .token.variable { - color: #e90; - } - - .token.important, - .token.bold { - font-weight: bold; - } - .token.italic { - font-style: italic; - } - - .token.entity { - cursor: help; - } -`; diff --git a/src/plugins/index.ts b/src/plugins/index.ts index 0444ea8..68fcc95 100644 --- a/src/plugins/index.ts +++ b/src/plugins/index.ts @@ -3,6 +3,4 @@ export { renderIdentityOrAddressPlugin, } from "./renderMentionIdentityUser"; export { sanitizeHtmlPlugin } from "./sanitizeHtml"; -export { minHeightPlugin } from "./minHeight"; -export { maxLinesPlugin } from "./maxLines"; export { highLightPlugin } from "./highlightCode"; diff --git a/src/plugins/maxLines.ts b/src/plugins/maxLines.ts deleted file mode 100644 index 4cc1afa..0000000 --- a/src/plugins/maxLines.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { Plugin, PreviewerProps } from "../types"; - -export function maxLinesPlugin(line: PreviewerProps["maxLines"]): Plugin { - return { - name: "max-lines", - - collectCss(css) { - if (!line) { - return ""; - } - - return css` - display: -webkit-box; - -webkit-line-clamp: ${line}; - -webkit-box-orient: vertical; - overflow: hidden; - `; - }, - }; -} diff --git a/src/plugins/minHeight.ts b/src/plugins/minHeight.ts deleted file mode 100644 index 4df255a..0000000 --- a/src/plugins/minHeight.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { Plugin, PreviewerProps } from "../types"; - -export function minHeightPlugin( - minHeight: PreviewerProps["minHeight"], -): Plugin { - return { - name: "min-height", - - collectCss(css) { - if (!minHeight) { - return ""; - } - - return css` - min-height: ${minHeight}px; - `; - }, - }; -} diff --git a/src/plugins/renderMentionIdentityUser.ts b/src/plugins/renderMentionIdentityUser.ts index ae1ffcb..1831f04 100644 --- a/src/plugins/renderMentionIdentityUser.ts +++ b/src/plugins/renderMentionIdentityUser.ts @@ -47,16 +47,6 @@ export function renderMentionIdentityUserPlugin( return { name: "render-mention-identity-user", - collectCss(css) { - return css` - ${containerElement.tag}.${containerElement.className} { - display: inline-flex; - /* do not know why, but works and looks normal */ - vertical-align: bottom; - } - `; - }, - markedOptions(options) { const renderer = options.renderer!; @@ -98,6 +88,7 @@ export function renderMentionIdentityUserPlugin( const { el } = createAppContainer(); const targetRoot = createRoot(el); targetRoot.render( + // @ts-ignore cloneElement(IdentityComponent, { address, network, diff --git a/src/styles.css b/src/styles.css new file mode 100644 index 0000000..56ebb1c --- /dev/null +++ b/src/styles.css @@ -0,0 +1,331 @@ +/** + * prism.js default theme for JavaScript, CSS and HTML + * Based on dabblet (http://dabblet.com) + * @author Lea Verou + */ +.markdown-body, +.html-body { + code[class*="language-"], + pre[class*="language-"] { + color: black; + background: none; + text-shadow: 0 1px white; + font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; + font-size: 1em; + text-align: left; + white-space: pre; + word-spacing: normal; + word-break: normal; + word-wrap: normal; + line-height: 1.5; + + -moz-tab-size: 4; + -o-tab-size: 4; + tab-size: 4; + + -webkit-hyphens: none; + -moz-hyphens: none; + -ms-hyphens: none; + hyphens: none; + } + + pre[class*="language-"]::-moz-selection, + pre[class*="language-"] ::-moz-selection, + code[class*="language-"]::-moz-selection, + code[class*="language-"] ::-moz-selection { + text-shadow: none; + background: #b3d4fc; + } + + pre[class*="language-"]::selection, + pre[class*="language-"] ::selection, + code[class*="language-"]::selection, + code[class*="language-"] ::selection { + text-shadow: none; + background: #b3d4fc; + } + + @media print { + code[class*="language-"], + pre[class*="language-"] { + text-shadow: none; + } + } + + /* Code blocks */ + pre[class*="language-"] { + padding: 1em; + margin: 0.5em 0; + overflow: auto; + } + + :not(pre) > code[class*="language-"], + pre[class*="language-"] { + background: #f5f2f0; + } + + /* Inline code */ + :not(pre) > code[class*="language-"] { + padding: 0.1em; + border-radius: 0.3em; + white-space: normal; + } + + .token.comment, + .token.prolog, + .token.doctype, + .token.cdata { + color: slategray; + } + + .token.punctuation { + color: #999; + } + + .token.namespace { + opacity: 0.7; + } + + .token.property, + .token.tag, + .token.boolean, + .token.number, + .token.constant, + .token.symbol, + .token.deleted { + color: #905; + } + + .token.selector, + .token.attr-name, + .token.string, + .token.char, + .token.builtin, + .token.inserted { + color: #690; + } + + .token.operator, + .token.entity, + .token.url, + .language-css .token.string, + .style .token.string { + color: #9a6e3a; + /* This background color was intended by the author of this theme. */ + background: hsla(0, 0%, 100%, 0.5); + } + + .token.atrule, + .token.attr-value, + .token.keyword { + color: #07a; + } + + .token.function, + .token.class-name { + color: #dd4a68; + } + + .token.regex, + .token.important, + .token.variable { + color: #e90; + } + + .token.important, + .token.bold { + font-weight: bold; + } + .token.italic { + font-style: italic; + } + + .token.entity { + cursor: help; + } +} + +.markdown-body, +.html-body { + /* base font */ + font-size: 14px; + font-weight: 500; + line-height: 20px; + + word-break: normal; + + h1, + h2, + h3, + h4, + h5, + h6 { + font-weight: 600; + + margin-top: 24px; + margin-bottom: 16px; + + :first-child { + margin-top: 0; + } + :last-child { + margin-bottom: 0; + } + + & b, + & strong { + font-weight: inherit; + } + } + + h1 { + line-height: 28px; + font-size: 20px; + } + + h2 { + line-height: 24px; + font-size: 18px; + } + + h3 { + line-height: 24px; + font-size: 16px; + } + + h4 { + line-height: 24px; + font-size: 14px; + } + + p { + word-break: break-word; + line-height: 24px !important; + } + + ol, + ul { + padding-left: 1.25em; + } + + ul { + list-style-type: disc; + } + + blockquote { + margin: 0; + padding-left: 0.75em; + border-left: 4px solid #eee; + } + + pre { + -ms-overflow-style: none; + scrollbar-width: none; + + ::-webkit-scrollbar { + display: none; + } + + * { + font-family: i-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, + Liberation Mono, monospace !important; + } + + margin: 8px 0; + padding: 0 8px; + background-color: #f0f3f8; + border-radius: 4px; + white-space: pre-wrap !important; + overflow-x: scroll; + + > code { + padding: 0 !important; + background: transparent !important; + white-space: pre-wrap !important; + display: inline; + + span.identifier { + white-space: nowrap !important; + } + } + } + + code { + font-family: i-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, + Liberation Mono, monospace !important; + padding: 2px 8px; + background-color: #f0f3f8; + border-radius: 4px; + } + + a { + color: #1f70c7; + cursor: pointer; + text-decoration: none; + } + + img { + max-width: 100%; + } + + p a::selection { + background-color: transparent !important; + color: inherit; + } + + th, + td { + border: 1px solid #e2e8f0; + } + + table { + margin: 8px 0; + border-collapse: collapse; + max-width: 100%; + overflow: auto; + display: block; + } + + th { + padding: 10px 16px; + background-color: #f0f3f8; + font-weight: bold; + color: #1e2134; + min-width: 100px; + } + + td { + padding: 10px 16px; + color: #1e2134; + } + + tbody tr:nth-child(even) { + background-color: #fbfcfe; + } + + hr { + background-color: #e2e8f0; + height: 1px; + border: none; + margin: 16px 0; + } + + /* NOTE: forced remove token background */ + code[class*="language-"], + pre[class*="language-"] { + .token { + background: transparent; + } + } +} + +/* renderMentionIdentityUser.ts */ +/* containerElement */ +.markdown-body, +.html-body { + & span.mention-identity-user-app { + display: inline-flex; + /* do not know why, but works and looks normal */ + vertical-align: bottom; + } +} diff --git a/src/types.ts b/src/types.ts index f9a5dc5..40fd98d 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,9 +1,5 @@ import React from "react"; import type { marked } from "marked"; -import type { - FlattenInterpolation, - ThemedCssFunction, -} from "styled-components"; export type PreviewerProps = { plugins?: Plugin[]; @@ -27,19 +23,11 @@ export type PreviewerProps = { maxLines?: number | string; }; -export type HtmlProps = React.PropsWithChildren<{ - extraCss?: (FlattenInterpolation | string)[]; -}>; - export type Plugin = { /** * @description Plugin name, unique */ name: string; - /** - * @description Apply css in `HtmlPreview.html-body` or `MarkdownPreviewer.markdown-body` - */ - collectCss?(css: ThemedCssFunction): FlattenInterpolation | string; /** * @description Only works on `MarkdownPreviewer`