This commit is contained in:
parent
b48e346001
commit
f50e7e9b71
4 changed files with 48 additions and 35 deletions
34
README.md
34
README.md
|
|
@ -3,37 +3,3 @@
|
|||
```sh
|
||||
pnpm install https://git.methanium.net/methanium/ui/releases/download/latest/methanium-ui.tgz
|
||||
```
|
||||
|
||||
## Markdown
|
||||
|
||||
The renderer is available from the package root. The live editor, compact text
|
||||
renderer, and emoji APIs use the `@methanium/ui/markdown` entry point.
|
||||
|
||||
```tsx
|
||||
import { Markdown } from "@methanium/ui";
|
||||
import {
|
||||
EmojiProvider,
|
||||
Input,
|
||||
createEmojiRegistry,
|
||||
} from "@methanium/ui/markdown";
|
||||
|
||||
const registry = createEmojiRegistry({
|
||||
customEmojis: [
|
||||
{
|
||||
shortcode: ":party_parrot:",
|
||||
aliases: [":parrot_party:"],
|
||||
src: "/emoji/party-parrot.webp",
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
<EmojiProvider registry={registry}>
|
||||
<Input value={value} setValue={setValue} />
|
||||
<Markdown content={value} />
|
||||
</EmojiProvider>;
|
||||
```
|
||||
|
||||
Custom shortcodes and aliases must be unique and may not collide with built-in
|
||||
Twemoji names. Twemoji graphics are bundled locally and do not use a CDN. The
|
||||
graphics are provided by the [Twemoji project](https://github.com/jdecked/twemoji)
|
||||
under CC-BY 4.0; code is licensed under MIT.
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@methanium/ui",
|
||||
"version": "0.0.25",
|
||||
"version": "0.0.26",
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ import { EmojiProvider, useEmojiRegistry } from "./emoji-context";
|
|||
import type { EmojiRegistry } from "./emoji-data";
|
||||
import { parseCodeMeta, remarkCodeMeta } from "./markdown-meta";
|
||||
import { remarkEmoji } from "./remark-emoji";
|
||||
import { remarkSmallMuted } from "./remark-small-muted";
|
||||
|
||||
export type MarkdownTheme = "light" | "dark";
|
||||
export type MarkdownVariant = "article" | "compact";
|
||||
|
|
@ -147,6 +148,7 @@ function Markdown({
|
|||
remarkMath,
|
||||
remarkBreaks,
|
||||
remarkCodeMeta,
|
||||
remarkSmallMuted,
|
||||
[remarkEmoji, { registry }],
|
||||
];
|
||||
|
||||
|
|
|
|||
45
src/markdown/remark-small-muted.ts
Normal file
45
src/markdown/remark-small-muted.ts
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
import type { Emphasis, Parent, Root, Text } from "mdast";
|
||||
import { SKIP, visit } from "unist-util-visit";
|
||||
|
||||
const delimiter = "??++";
|
||||
|
||||
export function remarkSmallMuted() {
|
||||
return (tree: Root) => {
|
||||
visit(tree, "text", (node: Text, index, parent: Parent | undefined) => {
|
||||
if (index === undefined || !parent) return;
|
||||
|
||||
const children: Parent["children"] = [];
|
||||
let cursor = 0;
|
||||
let opening = node.value.indexOf(delimiter);
|
||||
|
||||
while (opening !== -1) {
|
||||
const contentStart = opening + delimiter.length;
|
||||
const closing = node.value.indexOf(delimiter, contentStart);
|
||||
if (closing === -1) break;
|
||||
|
||||
if (opening > cursor) {
|
||||
children.push({ type: "text", value: node.value.slice(cursor, opening) });
|
||||
}
|
||||
children.push({
|
||||
type: "emphasis",
|
||||
children: [{ type: "text", value: node.value.slice(contentStart, closing) }],
|
||||
data: {
|
||||
hName: "span",
|
||||
hProperties: { className: ["text-xs", "text-muted-foreground"] },
|
||||
},
|
||||
} satisfies Emphasis);
|
||||
|
||||
cursor = closing + delimiter.length;
|
||||
opening = node.value.indexOf(delimiter, cursor);
|
||||
}
|
||||
|
||||
if (children.length === 0) return;
|
||||
if (cursor < node.value.length) {
|
||||
children.push({ type: "text", value: node.value.slice(cursor) });
|
||||
}
|
||||
|
||||
parent.children.splice(index, 1, ...children);
|
||||
return [SKIP, index + children.length];
|
||||
});
|
||||
};
|
||||
}
|
||||
Loading…
Reference in a new issue