@gridui/markdown 0.0.0-stage → 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,3 +1,38 @@
1
- # Temporary Holding Version
1
+ # @gridui/markdown
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Render Markdown content using the existing GridUI theme. Import `Markdown` from
4
+ `@gridui/markdown`; load `@gridui/theme/styles.css` before
5
+ `@gridui/markdown/styles.css`. Consumers do not need a styling compiler.
6
+
7
+ ```tsx
8
+ import "@gridui/theme/styles.css";
9
+ import "@gridui/markdown/styles.css";
10
+ import { Markdown } from "@gridui/markdown";
11
+
12
+ <Markdown streaming={isReceiving}>{responseText}</Markdown>
13
+ ```
14
+
15
+ Pass the complete current text snapshot as `children`. Updates support unfinished
16
+ fenced code and other CommonMark syntax through `react-markdown`; GFM tables,
17
+ task lists, strikethrough and autolinks are enabled. `streaming` exposes
18
+ `aria-busy` without announcing every token. Applications own transport, buffering,
19
+ throttling, completion announcements, and scroll following. Parsing is per
20
+ snapshot, not an incremental parser or a network stream implementation.
21
+
22
+ Raw HTML is skipped. URLs pass through react-markdown's safe default transform;
23
+ there is no raw-HTML or unsafe URL-transform escape hatch. `components` can
24
+ replace semantic renderers, including code, links and images. Those trusted
25
+ renderers own their output and accessibility; never inject untrusted HTML.
26
+ Images use the supplied URLs, so the application owns remote-media policy.
27
+
28
+ Use `[1](#citation:guide)` with
29
+ `citations={[{ id: "guide", title: "Guide", href: "https://example.com" }]}`
30
+ to resolve application-supplied citations. IDs must be nonempty and unique.
31
+ Unknown citations and rejected URLs render without an active link. A custom
32
+ link renderer can compose the application's existing citation presentation.
33
+
34
+ Compose messages with native `article`/heading elements and `@gridui/follow-scroll`.
35
+ Keep author identity, timestamps, message actions, retries and persistence in the
36
+ application. The Streaming story demonstrates successive response snapshots.
37
+
38
+ See [release history](https://github.com/sudo-ui/GridUI-React-Monorepo/tree/main/packages-core/markdown/.changeset/history).
@@ -0,0 +1,8 @@
1
+ /**
2
+ * @author WMXPY
3
+ * @package Markdown
4
+ * @namespace Root
5
+ * @description Index
6
+ */
7
+ export type { MarkdownCitation, MarkdownComponents, MarkdownProps } from "./markdown/markdown";
8
+ export { Markdown } from "./markdown/markdown";
package/dist/index.js ADDED
@@ -0,0 +1,76 @@
1
+ // src/markdown/markdown.tsx
2
+ import { cn } from "@gridui/style-utils";
3
+ import ReactMarkdown, { defaultUrlTransform } from "react-markdown";
4
+ import remarkGfm from "remark-gfm";
5
+ import { jsx } from "react/jsx-runtime";
6
+ var defaultComponents = {
7
+ a: ({ node: _node, href, children, ...anchorProps }) => {
8
+ return href ? /* @__PURE__ */ jsx(
9
+ "a",
10
+ {
11
+ ...anchorProps,
12
+ href,
13
+ children
14
+ }
15
+ ) : /* @__PURE__ */ jsx("span", { children });
16
+ },
17
+ img: ({ node: _node, src, alt, ...imageProps }) => {
18
+ return src ? /* @__PURE__ */ jsx(
19
+ "img",
20
+ {
21
+ ...imageProps,
22
+ src,
23
+ alt: alt ?? ""
24
+ }
25
+ ) : /* @__PURE__ */ jsx("span", { children: alt });
26
+ }
27
+ };
28
+ var Markdown = (props) => {
29
+ const { children, streaming = false, components, citations = [], className, ...restProps } = props;
30
+ const sources = new Map(citations.map((citation) => {
31
+ return [
32
+ citation.id,
33
+ citation
34
+ ];
35
+ }));
36
+ if (sources.size !== citations.length || citations.some((citation) => {
37
+ return !citation.id;
38
+ })) {
39
+ throw new Error("Markdown citation IDs must be nonempty and unique.");
40
+ }
41
+ return /* @__PURE__ */ jsx(
42
+ "div",
43
+ {
44
+ ...restProps,
45
+ className: cn("gridui-markdown", className),
46
+ "aria-busy": streaming || void 0,
47
+ "data-streaming": streaming || void 0,
48
+ children: /* @__PURE__ */ jsx(
49
+ ReactMarkdown,
50
+ {
51
+ skipHtml: true,
52
+ remarkPlugins: [remarkGfm],
53
+ urlTransform: (url, key, node) => {
54
+ if (url.startsWith("#citation:")) {
55
+ const citation = sources.get(url.slice("#citation:".length));
56
+ if (citation && key === "href") {
57
+ node.properties.title = citation.title;
58
+ }
59
+ return citation ? defaultUrlTransform(citation.href) : "";
60
+ }
61
+ return defaultUrlTransform(url);
62
+ },
63
+ components: {
64
+ ...defaultComponents,
65
+ ...components
66
+ },
67
+ children
68
+ }
69
+ )
70
+ }
71
+ );
72
+ };
73
+ export {
74
+ Markdown
75
+ };
76
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/markdown/markdown.tsx"],
4
+ "sourcesContent": ["/**\n * @author WMXPY\n * @package Markdown\n * @namespace Markdown\n * @description Markdown\n */\n\nimport { cn } from \"@gridui/style-utils\";\nimport type { ComponentPropsWithRef, FC } from \"react\";\nimport ReactMarkdown, { type Components, defaultUrlTransform } from \"react-markdown\";\nimport remarkGfm from \"remark-gfm\";\n\nexport type MarkdownComponents = Components;\n\nexport type MarkdownCitation = {\n readonly id: string;\n readonly title: string;\n readonly href: string;\n};\n\nexport type MarkdownProps = Omit<ComponentPropsWithRef<\"div\">, \"children\" | \"dangerouslySetInnerHTML\"> & {\n readonly children: string;\n readonly streaming?: boolean;\n readonly components?: MarkdownComponents;\n readonly citations?: readonly MarkdownCitation[];\n};\n\nconst defaultComponents: MarkdownComponents = {\n a: ({ node: _node, href, children, ...anchorProps }) => {\n return href ? (<a\n {...anchorProps}\n href={href}\n >\n {children}\n </a>) : (<span>\n {children}\n </span>);\n },\n img: ({ node: _node, src, alt, ...imageProps }) => {\n return src ? (<img\n {...imageProps}\n src={src}\n alt={alt ?? \"\"}\n />) : (<span>\n {alt}\n </span>);\n },\n};\n\n/** Renders the current document snapshot; transport and update scheduling stay with the host. */\nexport const Markdown: FC<MarkdownProps> = (props: MarkdownProps) => {\n const { children, streaming = false, components, citations = [], className, ...restProps } = props;\n const sources = new Map(citations.map((citation) => {\n return [\n citation.id,\n citation,\n ];\n }));\n if (sources.size !== citations.length || citations.some((citation) => {\n return !citation.id;\n })) {\n throw new Error(\"Markdown citation IDs must be nonempty and unique.\");\n }\n return (<div\n {...restProps}\n className={cn(\"gridui-markdown\", className)}\n aria-busy={streaming || undefined}\n data-streaming={streaming || undefined}\n >\n <ReactMarkdown\n skipHtml\n remarkPlugins={[remarkGfm]}\n urlTransform={(url, key, node) => {\n if (url.startsWith(\"#citation:\")) {\n const citation = sources.get(url.slice(\"#citation:\".length));\n if (citation && key === \"href\") {\n node.properties.title = citation.title;\n }\n return citation ? defaultUrlTransform(citation.href) : \"\";\n }\n return defaultUrlTransform(url);\n }}\n components={{\n ...defaultComponents,\n ...components,\n }}\n >\n {children}\n </ReactMarkdown>\n </div>);\n};\n"],
5
+ "mappings": ";AAOA,SAAS,UAAU;AAEnB,OAAO,iBAAkC,2BAA2B;AACpE,OAAO,eAAe;AAmBC;AAFvB,IAAM,oBAAwC;AAAA,EAC1C,GAAG,CAAC,EAAE,MAAM,OAAO,MAAM,UAAU,GAAG,YAAY,MAAM;AACpD,WAAO,OAAQ;AAAA,MAAC;AAAA;AAAA,QACX,GAAG;AAAA,QACJ;AAAA,QAEC;AAAA;AAAA,IACL,IAAS,oBAAC,UACL,UACL;AAAA,EACJ;AAAA,EACA,KAAK,CAAC,EAAE,MAAM,OAAO,KAAK,KAAK,GAAG,WAAW,MAAM;AAC/C,WAAO,MAAO;AAAA,MAAC;AAAA;AAAA,QACV,GAAG;AAAA,QACJ;AAAA,QACA,KAAK,OAAO;AAAA;AAAA,IAChB,IAAO,oBAAC,UACH,eACL;AAAA,EACJ;AACJ;AAGO,IAAM,WAA8B,CAAC,UAAyB;AACjE,QAAM,EAAE,UAAU,YAAY,OAAO,YAAY,YAAY,CAAC,GAAG,WAAW,GAAG,UAAU,IAAI;AAC7F,QAAM,UAAU,IAAI,IAAI,UAAU,IAAI,CAAC,aAAa;AAChD,WAAO;AAAA,MACH,SAAS;AAAA,MACT;AAAA,IACJ;AAAA,EACJ,CAAC,CAAC;AACF,MAAI,QAAQ,SAAS,UAAU,UAAU,UAAU,KAAK,CAAC,aAAa;AAClE,WAAO,CAAC,SAAS;AAAA,EACrB,CAAC,GAAG;AACA,UAAM,IAAI,MAAM,oDAAoD;AAAA,EACxE;AACA,SAAQ;AAAA,IAAC;AAAA;AAAA,MACJ,GAAG;AAAA,MACJ,WAAW,GAAG,mBAAmB,SAAS;AAAA,MAC1C,aAAW,aAAa;AAAA,MACxB,kBAAgB,aAAa;AAAA,MAE7B;AAAA,QAAC;AAAA;AAAA,UACG,UAAQ;AAAA,UACR,eAAe,CAAC,SAAS;AAAA,UACzB,cAAc,CAAC,KAAK,KAAK,SAAS;AAC9B,gBAAI,IAAI,WAAW,YAAY,GAAG;AAC9B,oBAAM,WAAW,QAAQ,IAAI,IAAI,MAAM,aAAa,MAAM,CAAC;AAC3D,kBAAI,YAAY,QAAQ,QAAQ;AAC5B,qBAAK,WAAW,QAAQ,SAAS;AAAA,cACrC;AACA,qBAAO,WAAW,oBAAoB,SAAS,IAAI,IAAI;AAAA,YAC3D;AACA,mBAAO,oBAAoB,GAAG;AAAA,UAClC;AAAA,UACA,YAAY;AAAA,YACR,GAAG;AAAA,YACH,GAAG;AAAA,UACP;AAAA,UAEC;AAAA;AAAA,MACL;AAAA;AAAA,EACJ;AACJ;",
6
+ "names": []
7
+ }
@@ -0,0 +1,22 @@
1
+ /**
2
+ * @author WMXPY
3
+ * @package Markdown
4
+ * @namespace Markdown
5
+ * @description Markdown
6
+ */
7
+ import type { ComponentPropsWithRef, FC } from "react";
8
+ import { type Components } from "react-markdown";
9
+ export type MarkdownComponents = Components;
10
+ export type MarkdownCitation = {
11
+ readonly id: string;
12
+ readonly title: string;
13
+ readonly href: string;
14
+ };
15
+ export type MarkdownProps = Omit<ComponentPropsWithRef<"div">, "children" | "dangerouslySetInnerHTML"> & {
16
+ readonly children: string;
17
+ readonly streaming?: boolean;
18
+ readonly components?: MarkdownComponents;
19
+ readonly citations?: readonly MarkdownCitation[];
20
+ };
21
+ /** Renders the current document snapshot; transport and update scheduling stay with the host. */
22
+ export declare const Markdown: FC<MarkdownProps>;
@@ -0,0 +1,85 @@
1
+ /*! tailwindcss v4.3.4 | MIT License | https://tailwindcss.com */
2
+ @layer theme, base, components, utilities;
3
+ @layer utilities;
4
+ @layer components {
5
+ .gridui-markdown {
6
+ overflow-wrap: anywhere;
7
+ color: var(--gridui-foreground);
8
+ line-height: 1.6;
9
+ }
10
+ .gridui-markdown > :first-child {
11
+ margin-block-start: 0;
12
+ }
13
+ .gridui-markdown > :last-child {
14
+ margin-block-end: 0;
15
+ }
16
+ .gridui-markdown :where(p, ul, ol, pre, blockquote, table) {
17
+ margin-block: var(--gridui-space-16);
18
+ }
19
+ .gridui-markdown :where(ul, ol) {
20
+ padding-inline-start: var(--gridui-space-24);
21
+ }
22
+ .gridui-markdown ul {
23
+ list-style: disc;
24
+ }
25
+ .gridui-markdown ol {
26
+ list-style: decimal;
27
+ }
28
+ .gridui-markdown :where(h1, h2, h3, h4, h5, h6) {
29
+ margin-block: var(--gridui-space-24) var(--gridui-space-8);
30
+ font-weight: 600;
31
+ line-height: 1.3;
32
+ }
33
+ .gridui-markdown h1 {
34
+ font-size: 1.75em;
35
+ }
36
+ .gridui-markdown h2 {
37
+ font-size: 1.5em;
38
+ }
39
+ .gridui-markdown h3 {
40
+ font-size: 1.25em;
41
+ }
42
+ .gridui-markdown a {
43
+ color: var(--gridui-link);
44
+ text-decoration: underline;
45
+ text-underline-offset: 0.15em;
46
+ }
47
+ .gridui-markdown :where(pre, code) {
48
+ font-family: monospace;
49
+ background: var(--gridui-surface);
50
+ }
51
+ .gridui-markdown pre {
52
+ overflow: auto;
53
+ padding: var(--gridui-space-16);
54
+ border: 1px solid var(--gridui-border);
55
+ white-space: pre;
56
+ }
57
+ .gridui-markdown :not(pre) > code {
58
+ padding-inline: var(--gridui-space-4);
59
+ }
60
+ .gridui-markdown blockquote {
61
+ padding-inline-start: var(--gridui-space-16);
62
+ border-inline-start: 2px solid var(--gridui-border);
63
+ color: var(--gridui-muted);
64
+ }
65
+ .gridui-markdown table {
66
+ display: block;
67
+ max-width: 100%;
68
+ overflow: auto;
69
+ border-collapse: collapse;
70
+ }
71
+ .gridui-markdown :where(th, td) {
72
+ padding: var(--gridui-space-8) var(--gridui-space-12);
73
+ border: 1px solid var(--gridui-border);
74
+ text-align: start;
75
+ }
76
+ .gridui-markdown img {
77
+ max-width: 100%;
78
+ height: auto;
79
+ }
80
+ .gridui-markdown hr {
81
+ border: 0;
82
+ border-block-start: 1px solid var(--gridui-border);
83
+ margin-block: var(--gridui-space-24);
84
+ }
85
+ }
@@ -0,0 +1,40 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "name": "@gridui/markdown",
4
+ "version": "0.0.0",
5
+ "category": "core",
6
+ "description": "GridUI React Markdown content with streaming updates",
7
+ "usage": "Render Markdown content using the existing GridUI theme. Import `Markdown` from `@gridui/markdown`; load `@gridui/theme/styles.css` before `@gridui/markdown/styles.css`. Consumers do not need a styling compiler.",
8
+ "documentation": [
9
+ "README.md"
10
+ ],
11
+ "exports": [
12
+ {
13
+ "name": "Markdown",
14
+ "kind": "component",
15
+ "importPath": "@gridui/markdown"
16
+ },
17
+ {
18
+ "name": "MarkdownCitation",
19
+ "kind": "type",
20
+ "importPath": "@gridui/markdown"
21
+ },
22
+ {
23
+ "name": "MarkdownComponents",
24
+ "kind": "type",
25
+ "importPath": "@gridui/markdown"
26
+ },
27
+ {
28
+ "name": "MarkdownProps",
29
+ "kind": "type",
30
+ "importPath": "@gridui/markdown"
31
+ }
32
+ ],
33
+ "styles": [
34
+ "@gridui/theme/styles.css",
35
+ "@gridui/markdown/styles.css"
36
+ ],
37
+ "examples": [
38
+ "https://github.com/sudo-ui/GridUI-React-Monorepo/blob/main/packages-core/markdown/stories/markdown.stories.tsx"
39
+ ]
40
+ }
package/package.json CHANGED
@@ -1,6 +1,54 @@
1
1
  {
2
2
  "name": "@gridui/markdown",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "0.0.0",
4
+ "description": "GridUI React Markdown content with streaming updates",
5
+ "license": "UNLICENSED",
6
+ "type": "module",
7
+ "files": [
8
+ "dist",
9
+ "README.md",
10
+ "docs"
11
+ ],
12
+ "sideEffects": [
13
+ "**/*.css"
14
+ ],
15
+ "exports": {
16
+ ".": {
17
+ "types": "./dist/index.d.ts",
18
+ "import": "./dist/index.js"
19
+ },
20
+ "./styles.css": "./dist/styles.css"
21
+ },
22
+ "publishConfig": {
23
+ "access": "public"
24
+ },
25
+ "peerDependencies": {
26
+ "react": "^19.2.0",
27
+ "react-dom": "^19.2.0"
28
+ },
29
+ "dependencies": {
30
+ "@gridui/style-utils": "^2.2.0",
31
+ "@gridui/theme": "^2.5.1",
32
+ "react-markdown": "10.1.0",
33
+ "remark-gfm": "4.0.1"
34
+ },
35
+ "devDependencies": {
36
+ "@gridui-internal/configuration": "0.0.0-internal",
37
+ "@jest/globals": "30.5.2",
38
+ "@storybook/react-vite": "10.6.5",
39
+ "@types/jest": "30.0.0",
40
+ "@types/node": "26.6.6",
41
+ "@types/react": "19.3.0",
42
+ "@types/react-dom": "19.3.0",
43
+ "jest": "30.5.2",
44
+ "react": "19.3.1",
45
+ "react-dom": "19.3.1",
46
+ "typescript": "6.0.3"
47
+ },
48
+ "scripts": {
49
+ "build": "node ../../scripts/compilation/package.ts",
50
+ "compile": "tsc --project tsconfig.json",
51
+ "test": "jest",
52
+ "coverage": "jest --coverage"
53
+ }
6
54
  }