Added support for <sub> <sup> in markdown (#1215)
* Add support for sub and superscript in markdown * Removed empty line as per lint * renamed schema to rehypeSanitizeSchema to make it less generic * Linting fixes * Update components/text.js Co-authored-by: ekzyis <ek@stacker.news> * Reverting changes: remove rehype-raw&sanitize, clean up * Draft iteration of rehypeStyler plugin * rehypeStyler visiting element nodes properly to catch tag-text-tag patterns * Refreshed package-lock --------- Co-authored-by: ekzyis <ek@stacker.news>
This commit is contained in:
parent
ddaec36617
commit
a95402e3be
|
@ -15,7 +15,7 @@ import copy from 'clipboard-copy'
|
|||
import ZoomableImage, { decodeOriginalUrl } from './image'
|
||||
import { IMGPROXY_URL_REGEXP, parseInternalLinks, parseEmbedUrl } from '@/lib/url'
|
||||
import reactStringReplace from 'react-string-replace'
|
||||
import { rehypeInlineCodeProperty } from '@/lib/md'
|
||||
import { rehypeInlineCodeProperty, rehypeSubscript, rehypeSuperscript } from '@/lib/md'
|
||||
import { Button } from 'react-bootstrap'
|
||||
import { useRouter } from 'next/router'
|
||||
import Link from 'next/link'
|
||||
|
@ -313,7 +313,7 @@ export default memo(function Text ({ rel, imgproxyUrls, children, tab, itemId, o
|
|||
img: Img
|
||||
}}
|
||||
remarkPlugins={[gfm, mention, sub]}
|
||||
rehypePlugins={[rehypeInlineCodeProperty]}
|
||||
rehypePlugins={[rehypeInlineCodeProperty, rehypeSuperscript, rehypeSubscript]}
|
||||
>
|
||||
{children}
|
||||
</ReactMarkdown>
|
||||
|
|
|
@ -252,3 +252,15 @@ img.fullScreen {
|
|||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
|
||||
/* Utility classes used in rehype plugins in md.js */
|
||||
.subscript {
|
||||
vertical-align: sub;
|
||||
font-size: smaller;
|
||||
}
|
||||
|
||||
.superscript {
|
||||
vertical-align: super;
|
||||
font-size: smaller;
|
||||
}
|
32
lib/md.js
32
lib/md.js
|
@ -2,6 +2,7 @@ import { gfmFromMarkdown } from 'mdast-util-gfm'
|
|||
import { visit } from 'unist-util-visit'
|
||||
import { gfm } from 'micromark-extension-gfm'
|
||||
import { fromMarkdown } from 'mdast-util-from-markdown'
|
||||
import { superscript, subscript } from '../components/text.module.css'
|
||||
|
||||
export function mdHas (md, test) {
|
||||
if (!md) return []
|
||||
|
@ -31,6 +32,37 @@ export function rehypeInlineCodeProperty () {
|
|||
}
|
||||
}
|
||||
|
||||
function rehypeStyler (startTag, endTag, className) {
|
||||
return function (tree) {
|
||||
visit(tree, 'element', (node) => {
|
||||
for (let i = 0; i < node.children.length; i += 1) {
|
||||
const start = node.children[i]
|
||||
const text = node.children[i + 1]
|
||||
const end = node.children[i + 2]
|
||||
|
||||
// is this a children slice wrapped with the tags we're looking for?
|
||||
const isWrapped =
|
||||
start?.type === 'raw' && start?.value === startTag &&
|
||||
text?.type === 'text' &&
|
||||
end?.type === 'raw' && end?.value === endTag
|
||||
if (!isWrapped) continue
|
||||
|
||||
const newChildren = {
|
||||
type: 'element',
|
||||
tagName: 'span',
|
||||
properties: { className: [className] },
|
||||
children: [{ type: 'text', value: text.value }]
|
||||
}
|
||||
node.children.splice(i, 3, newChildren)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Explicitely defined start/end tags & which CSS class from text.module.css to apply
|
||||
export const rehypeSuperscript = () => rehypeStyler('<sup>', '</sup>', superscript)
|
||||
export const rehypeSubscript = () => rehypeStyler('<sub>', '</sub>', subscript)
|
||||
|
||||
export function extractUrls (md) {
|
||||
if (!md) return []
|
||||
const tree = fromMarkdown(md, {
|
||||
|
|
Loading…
Reference in New Issue