From 3abeaf355c5e99b7179b61b863a673c11fd8836a Mon Sep 17 00:00:00 2001 From: jaywcjlove <398188662@qq.com> Date: Fri, 2 Sep 2022 11:44:25 +0800 Subject: [PATCH] feat: support custom style & ignore content syntax. --- README.md | 47 ++++++++++++++++++++++++++++++------- package.json | 2 ++ src/conf/default.md.css | 15 ++++++++++++ src/utils/css.ts | 12 +++++++++- src/utils/markdownToHTML.ts | 30 ++++++++++++++++------- 5 files changed, 88 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 582ac9a..084be39 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,9 @@ -微信公众号文章 Markdown 编辑器,使用 markdown 语法创建一篇简介美观大方的微信公众号图文。由于发版本麻烦,和一些功能无法扩展停滞开发了,未来不再开发 Chrome 的工具(暂存在 chrome 分支),通过 web 版本定制更丰富的功能。 +![](https://user-images.githubusercontent.com/1680273/187980169-e648f2a4-41f0-496f-8450-7f5ffc255059.png) + +微信公众号文章 Markdown 在线编辑器,使用 markdown 语法创建一篇简介美观大方的微信公众号图文。由于发版本麻烦,和一些功能无法扩展停滞开发了,未来不再开发 Chrome 的工具(暂存在 chrome 分支),通过 web 版本定制更丰富的功能。 ## 功能特性 @@ -56,10 +58,11 @@ Inline Code `{code: 0}` ### 支持 GFM 脚注 -这是一个简单的脚注[^1]。 页面最后有一些额外的文字描述。注意这不是完整的注脚[^2]。 +这是一个简单的 Markdown[^1] 语法的脚注[^2]。 页面最后有一些额外的文字描述。注意这不是完整的注脚[^3]特性。 -[^1]: https://github.github.com/gfm/ -[^2]: 微信文章不支持锚点跳转和打开第三方 URL 超链接,所以不支持完整的注脚 +[^1]: GitHub 风格的 Markdown 规范 https://github.github.com/gfm/ +[^2]: 脚注 https://github.blog/changelog/2021-09-30-footnotes-now-supported-in-markdown-fields/ +[^3]: 微信文章不支持锚点跳转和打开第三方 URL 超链接,所以不支持完整的注脚特性。 ### 支持注释 @@ -72,6 +75,31 @@ Inline Code `{code: 0}` 音 yin +### 支持自定义样式 + + +在 Markdown 中 HTML 注释也可以用在 markdown 中,利用这一特点,为一些内容自定一样式。使用 HTML 注释 `` 让 Markdown 支持样式自定义。 + +```markdown +## 定义标题样式 + + +支持对某些文字变更样式,如_文字颜色_,文字颜色将被设置为红色(red)。 +``` + +⚠️ 注意:这一特性可能适用于有一定 css 前端基础知识的用户,不过它也非常简单,使用 `` 结束,中间包裹 css 样式,如 `color: red;` 设置文字红色。 + + +### 标记忽略内容 + +此特性利用 HTML 注释在 markdown 中被忽略的特性,标记需要忽略的内容,标记开始 ``,标记结束 ``,被标记的内容在微信 Markdown 编辑器预览中不显示。在其它预览工具中展示内容,比如 GitHub 中能展示。 + +```markdown +# 注释忽略 + +内容在微信 Markdown 编辑器预览中不显示。在其它预览工具中展示内容。 +``` + ## 部署 [![Docker Image Version (latest by date)](https://img.shields.io/docker/v/wcjiang/wxmp?logo=docker)](https://hub.docker.com/r/wcjiang/wxmp) [![Docker Image Size (latest by date)](https://img.shields.io/docker/image-size/wcjiang/wxmp?logo=docker)](https://hub.docker.com/r/wcjiang/wxmp) [![Docker Pulls](https://img.shields.io/docker/pulls/wcjiang/wxmp?logo=docker)](https://hub.docker.com/r/wcjiang/wxmp) @@ -98,16 +126,19 @@ docker run --name wxmp -itd -p 96611:3000 ghcr.io/jaywcjlove/wxmp:latest http://localhost:96611/ ``` -## Contributors +## 贡献者 -As always, thanks to our amazing contributors! +一如既往,感谢我们出色的贡献者! -Made with [github-action-contributors](https://github.com/jaywcjlove/github-action-contributors). +上图贡献者列表,由 [action-contributors](https://github.com/jaywcjlove/github-action-contributors)[^4] 自动生成贡献者图片。 + + +[^4]: Action Contributors https://github.com/jaywcjlove/github-action-contributors ## License -Licensed under the MIT License. +根据 MIT 许可证获得许可。 diff --git a/package.json b/package.json index 2c2f028..cd9d6fa 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,8 @@ "react-dom": "^18.2.0", "react-hot-toast": "^2.3.0", "react-router-dom": "^6.3.0", + "rehype-attr": "^2.0.8", + "rehype-ignore": "^1.0.1", "rehype-prism-plus": "^1.5.0", "rehype-raw": "^6.1.1", "rehype-stringify": "^9.0.3", diff --git a/src/conf/default.md.css b/src/conf/default.md.css index e6241ea..58e46ce 100644 --- a/src/conf/default.md.css +++ b/src/conf/default.md.css @@ -163,6 +163,21 @@ th { font-size: 12px; } +figure { + margin: 0; +} + +.image-warpper { + text-align: center; + margin-bottom: 0rem; + visibility: visible; +} + +.image { + display: initial; + max-width: 100%; +} + .comment { color: #6a737d; } .property { color: #6f42c1; } .function { color: #6f42c1; } diff --git a/src/utils/css.ts b/src/utils/css.ts index fad5bb6..4676b0d 100644 --- a/src/utils/css.ts +++ b/src/utils/css.ts @@ -1,4 +1,4 @@ -import { RootContent, Element, Text } from 'hast'; +import { RootContent, Element, Text, Root } from 'hast'; export const getBlock = (data: any, str: string = '') => { if (data && data.data && data.data.type === 'Declaration') { @@ -87,4 +87,14 @@ export const footnotesLabel = (node: Element) => { type: 'text', value: `[${label}]` }]; +} + +export const imagesStyle = (node: Element, parent: Root | Element | null) => { + if (parent?.type === 'element' && parent.tagName === 'p' && node?.type === 'element' && node.tagName === 'img') { + parent.tagName = 'figure'; + if (!parent.properties) parent.properties = {} + parent.properties.className = ['image-warpper'] + if (!node.properties) node.properties = {} + node.properties.className = ['image'] + } } \ No newline at end of file diff --git a/src/utils/markdownToHTML.ts b/src/utils/markdownToHTML.ts index 4f29bb2..89268dc 100644 --- a/src/utils/markdownToHTML.ts +++ b/src/utils/markdownToHTML.ts @@ -7,9 +7,11 @@ import remarkGfm from 'remark-gfm'; import remarkRehype from 'remark-rehype'; import rehypePrism from 'rehype-prism-plus'; import rehypeRaw from 'rehype-raw'; +import rehypeAttrs from 'rehype-attr'; +import rehypeIgnore from 'rehype-ignore'; import rehypeRewrite from 'rehype-rewrite'; import stringify from 'rehype-stringify'; -import { cssdata, spaceEscape, footnotes, footnotesLabel } from './css'; +import { cssdata, spaceEscape, footnotes, footnotesLabel, imagesStyle } from './css'; export type MarkdownToHTMLOptions = { @@ -25,14 +27,18 @@ export function markdownToHTML(md: string, css: string, options: MarkdownToHTMLO }); // @ts-ignore const data = cssdata(ast.children.head); + console.log(data) const processor = unified() .use(remarkParse) + .use(remarkGfm) .use(remarkRehype, { allowDangerousHtml: true }) .use(rehypePrism) - .use(remarkGfm) .use(rehypeRaw) + .use(rehypeIgnore, { }) + .use(rehypeAttrs, { properties: 'attr' }) .use(rehypeRewrite, { rewrite: (node, index, parent) => { + // @ts-ignore if (node?.type === 'element' && node?.tagName === 'code' && parent?.type === 'element' && parent?.tagName === 'pre') { spaceEscape(node) } @@ -42,17 +48,23 @@ export function markdownToHTML(md: string, css: string, options: MarkdownToHTMLO if (node?.type === 'element' && node.tagName === 'sup') { footnotesLabel(node) } + if (node?.type === 'element' && node.tagName === 'img') { + imagesStyle(node, parent) + } + // Code Spans style if (node?.type === 'element' && node?.tagName === 'code' && parent?.type === 'element' && parent?.tagName !== 'pre') { if (!node.properties) node.properties = {} node.properties!.className = ['code-spans']; } - if (node?.type === 'element') { - if (node.tagName === 'input' && parent?.type === 'element') { - if (parent && parent.type === 'element') { - parent.children = parent?.children.filter(elm => (elm as Element).tagName !== 'input') - } - return; + // List TODO style + if (parent?.type === 'element' && node?.type === 'element' && node?.tagName === 'input') { + if (parent && parent.type === 'element') { + parent.children = parent?.children.filter(elm => (elm as Element).tagName !== 'input') } + return; + } + // Support *.md.css + if (node?.type === 'element') { if (!node.properties) { node.properties = {}; } @@ -67,7 +79,7 @@ export function markdownToHTML(md: string, css: string, options: MarkdownToHTMLO } if (!style) style = data[node.tagName]; if (style) { - node.properties.style = style; + node.properties.style = style + (node.properties.style || ''); } } }