semantic-renderer 1.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/LICENSE +21 -0
- package/README.md +192 -0
- package/dist/core/classifier.d.ts +13 -0
- package/dist/core/classifier.d.ts.map +1 -0
- package/dist/core/classifier.js +478 -0
- package/dist/core/classifier.js.map +1 -0
- package/dist/core/index.d.ts +3 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +3 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/types.d.ts +40 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +2 -0
- package/dist/core/types.js.map +1 -0
- package/dist/react/FallbackMarkdown.d.ts +8 -0
- package/dist/react/FallbackMarkdown.d.ts.map +1 -0
- package/dist/react/FallbackMarkdown.js +10 -0
- package/dist/react/FallbackMarkdown.js.map +1 -0
- package/dist/react/SemanticRenderer.d.ts +14 -0
- package/dist/react/SemanticRenderer.d.ts.map +1 -0
- package/dist/react/SemanticRenderer.js +37 -0
- package/dist/react/SemanticRenderer.js.map +1 -0
- package/dist/react/index.d.ts +10 -0
- package/dist/react/index.d.ts.map +1 -0
- package/dist/react/index.js +11 -0
- package/dist/react/index.js.map +1 -0
- package/dist/react/renderers/CodeExplanationRenderer.d.ts +10 -0
- package/dist/react/renderers/CodeExplanationRenderer.d.ts.map +1 -0
- package/dist/react/renderers/CodeExplanationRenderer.js +14 -0
- package/dist/react/renderers/CodeExplanationRenderer.js.map +1 -0
- package/dist/react/renderers/ComparisonRenderer.d.ts +10 -0
- package/dist/react/renderers/ComparisonRenderer.d.ts.map +1 -0
- package/dist/react/renderers/ComparisonRenderer.js +13 -0
- package/dist/react/renderers/ComparisonRenderer.js.map +1 -0
- package/dist/react/renderers/DataTableRenderer.d.ts +10 -0
- package/dist/react/renderers/DataTableRenderer.d.ts.map +1 -0
- package/dist/react/renderers/DataTableRenderer.js +51 -0
- package/dist/react/renderers/DataTableRenderer.js.map +1 -0
- package/dist/react/renderers/ProsConsRenderer.d.ts +10 -0
- package/dist/react/renderers/ProsConsRenderer.d.ts.map +1 -0
- package/dist/react/renderers/ProsConsRenderer.js +13 -0
- package/dist/react/renderers/ProsConsRenderer.js.map +1 -0
- package/dist/react/renderers/StepsRenderer.d.ts +10 -0
- package/dist/react/renderers/StepsRenderer.d.ts.map +1 -0
- package/dist/react/renderers/StepsRenderer.js +28 -0
- package/dist/react/renderers/StepsRenderer.js.map +1 -0
- package/dist/react/renderers/VerdictRenderer.d.ts +10 -0
- package/dist/react/renderers/VerdictRenderer.d.ts.map +1 -0
- package/dist/react/renderers/VerdictRenderer.js +13 -0
- package/dist/react/renderers/VerdictRenderer.js.map +1 -0
- package/package.json +85 -0
- package/src/react/styles.css +79 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Sagar Kalra / AutoPriseAI
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
# semantic-renderer
|
|
2
|
+
|
|
3
|
+
Intelligent LLM response renderer that detects the **semantic intent** of markdown responses and renders them with purpose-built visual components — not just "better markdown", but context-aware layouts.
|
|
4
|
+
|
|
5
|
+
A comparison response renders as side-by-side cards. A step-by-step guide renders as an interactive stepper. Pros and cons render as a green/red two-column layout. All automatically detected — zero prompt engineering required.
|
|
6
|
+
|
|
7
|
+
## What it detects
|
|
8
|
+
|
|
9
|
+
| Type | Trigger | Visual |
|
|
10
|
+
|------|---------|--------|
|
|
11
|
+
| **Pros & Cons** | Headings/bold with "pros/advantages" + "cons/disadvantages" | Two-column green/red layout with check/X icons |
|
|
12
|
+
| **Comparison** | 2+ `###` headings with bullet lists, or "vs"/"versus" | Side-by-side entity cards with colored headers |
|
|
13
|
+
| **Steps** | Ordered lists with 3+ items, or "Step N"/"Phase N" headings | Vertical stepper with numbered circles and expand/collapse |
|
|
14
|
+
| **Code + Explanation** | Single fenced code block + 2+ paragraphs of prose | Split view — code panel (55%) + explanation panel (45%) |
|
|
15
|
+
| **Data Table** | GFM table with 3+ rows and 3+ columns | Sortable, filterable table with row count |
|
|
16
|
+
| **Verdict** | Heading matching "verdict/conclusion/recommendation/summary/tldr" | Accent-bordered card with icon |
|
|
17
|
+
| **Default** | Everything else | Your existing markdown renderer (unchanged) |
|
|
18
|
+
|
|
19
|
+
## Install
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm install semantic-renderer
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Quick Start (React)
|
|
26
|
+
|
|
27
|
+
```tsx
|
|
28
|
+
import { SemanticRenderer } from 'semantic-renderer/react';
|
|
29
|
+
import 'semantic-renderer/react/styles.css';
|
|
30
|
+
|
|
31
|
+
function ChatMessage({ content, isStreaming }) {
|
|
32
|
+
return (
|
|
33
|
+
<SemanticRenderer
|
|
34
|
+
content={content}
|
|
35
|
+
isStreaming={isStreaming}
|
|
36
|
+
/>
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
That's it. The component classifies the markdown and picks the right renderer automatically. During streaming, it bypasses classification and renders plain markdown — zero risk to your streaming UX.
|
|
42
|
+
|
|
43
|
+
## Peer Dependencies
|
|
44
|
+
|
|
45
|
+
The React entry point uses these (you likely already have them):
|
|
46
|
+
|
|
47
|
+
```json
|
|
48
|
+
{
|
|
49
|
+
"react": ">=18.0.0",
|
|
50
|
+
"react-dom": ">=18.0.0",
|
|
51
|
+
"react-markdown": ">=9.0.0",
|
|
52
|
+
"framer-motion": ">=10.0.0",
|
|
53
|
+
"lucide-react": ">=0.300.0"
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
All are optional — the core classifier has zero dependencies.
|
|
58
|
+
|
|
59
|
+
## API
|
|
60
|
+
|
|
61
|
+
### `<SemanticRenderer />` (React)
|
|
62
|
+
|
|
63
|
+
```tsx
|
|
64
|
+
interface SemanticRendererProps {
|
|
65
|
+
/** The markdown content to render */
|
|
66
|
+
content: string;
|
|
67
|
+
/** Skip classification — render as plain markdown (useful for streaming) */
|
|
68
|
+
isStreaming?: boolean;
|
|
69
|
+
/** CSS class for the wrapper div */
|
|
70
|
+
className?: string;
|
|
71
|
+
/** Custom markdown renderer component (defaults to react-markdown) */
|
|
72
|
+
fallback?: React.ComponentType<{ content: string }>;
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### `classify()` (Core — framework-agnostic)
|
|
77
|
+
|
|
78
|
+
```ts
|
|
79
|
+
import { classify } from 'semantic-renderer';
|
|
80
|
+
|
|
81
|
+
const blocks = classify(markdownString);
|
|
82
|
+
// Returns: SemanticBlock[]
|
|
83
|
+
// Each block has: { id, type, rawMarkdown, meta }
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Use this if you want to build your own renderers (React Native, Vue, Svelte, etc.) on top of the classification engine.
|
|
87
|
+
|
|
88
|
+
### Block Types
|
|
89
|
+
|
|
90
|
+
```ts
|
|
91
|
+
type SemanticBlockType =
|
|
92
|
+
| 'comparison' // meta: ComparisonMeta
|
|
93
|
+
| 'steps' // meta: StepsMeta
|
|
94
|
+
| 'pros-cons' // meta: ProsConsMeta
|
|
95
|
+
| 'code-explanation' // meta: CodeExplanationMeta
|
|
96
|
+
| 'data-table' // meta: DataTableMeta
|
|
97
|
+
| 'verdict' // meta: VerdictMeta
|
|
98
|
+
| 'default'; // meta: {}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Theming
|
|
102
|
+
|
|
103
|
+
The default styles use CSS custom properties. Override them to match your app:
|
|
104
|
+
|
|
105
|
+
```css
|
|
106
|
+
:root {
|
|
107
|
+
--sem-accent: #6366f1; /* Primary accent (stepper circles, borders) */
|
|
108
|
+
--sem-border: #e5e7eb; /* Border color */
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Or in dark mode:
|
|
113
|
+
|
|
114
|
+
```css
|
|
115
|
+
.dark {
|
|
116
|
+
--sem-accent: #818cf8;
|
|
117
|
+
--sem-border: #374151;
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Using Your Own Markdown Renderer
|
|
122
|
+
|
|
123
|
+
If you already have a custom markdown component, pass it as `fallback`:
|
|
124
|
+
|
|
125
|
+
```tsx
|
|
126
|
+
import { SemanticRenderer } from 'semantic-renderer/react';
|
|
127
|
+
import 'semantic-renderer/react/styles.css';
|
|
128
|
+
import { MyMarkdownRenderer } from './MyMarkdownRenderer';
|
|
129
|
+
|
|
130
|
+
// Your component must accept a `content` string prop
|
|
131
|
+
const MyFallback = ({ content }) => <MyMarkdownRenderer source={content} />;
|
|
132
|
+
|
|
133
|
+
<SemanticRenderer content={content} fallback={MyFallback} />
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
The fallback is used for:
|
|
137
|
+
- Unclassified (default) blocks
|
|
138
|
+
- Inline markdown within semantic blocks (e.g., bullet text in pros/cons)
|
|
139
|
+
- Streaming content (when `isStreaming` is true)
|
|
140
|
+
|
|
141
|
+
## Using Individual Renderers
|
|
142
|
+
|
|
143
|
+
You can also import renderers individually:
|
|
144
|
+
|
|
145
|
+
```tsx
|
|
146
|
+
import { classify } from 'semantic-renderer';
|
|
147
|
+
import { ProsConsRenderer, VerdictRenderer } from 'semantic-renderer/react';
|
|
148
|
+
import 'semantic-renderer/react/styles.css';
|
|
149
|
+
|
|
150
|
+
const blocks = classify(content);
|
|
151
|
+
|
|
152
|
+
blocks.map(block => {
|
|
153
|
+
if (block.type === 'pros-cons') return <ProsConsRenderer block={block} Fallback={MyMarkdown} />;
|
|
154
|
+
if (block.type === 'verdict') return <VerdictRenderer block={block} Fallback={MyMarkdown} />;
|
|
155
|
+
return <MyMarkdown content={block.rawMarkdown} />;
|
|
156
|
+
});
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## How It Works
|
|
160
|
+
|
|
161
|
+
1. **Split** — The markdown is split into sections by `##`/`###` headings
|
|
162
|
+
2. **Detect** — Each section is tested against 6 detectors in priority order (first match wins)
|
|
163
|
+
3. **Extract** — The winning detector extracts structured metadata (e.g., pros list, step titles)
|
|
164
|
+
4. **Render** — Each block is rendered by its purpose-built component, with the original markdown as fallback
|
|
165
|
+
|
|
166
|
+
The classifier is pure TypeScript with zero dependencies — no ML models, no API calls, no parsing libraries. Just regex heuristics tuned on real LLM output patterns.
|
|
167
|
+
|
|
168
|
+
## Fallback Safety
|
|
169
|
+
|
|
170
|
+
Every renderer validates its metadata before rendering. If anything is malformed, it falls back to your markdown renderer with the original text. You'll never see a broken layout — worst case, you see the same markdown you'd see without this package.
|
|
171
|
+
|
|
172
|
+
## Examples
|
|
173
|
+
|
|
174
|
+
Ask any LLM these prompts to see each renderer in action:
|
|
175
|
+
|
|
176
|
+
- **Pros/Cons**: "What are the pros and cons of microservices?"
|
|
177
|
+
- **Comparison**: "Compare React vs Vue vs Angular"
|
|
178
|
+
- **Steps**: "How to deploy a Node.js app to AWS step by step?"
|
|
179
|
+
- **Code+Explanation**: "Explain this code: `const debounce = (fn, ms) => { let t; return (...a) => { clearTimeout(t); t = setTimeout(() => fn(...a), ms); }; }`"
|
|
180
|
+
- **Data Table**: "Table of HTTP status codes with descriptions and examples"
|
|
181
|
+
- **Verdict**: "What's your verdict on using TypeScript for a new project?"
|
|
182
|
+
|
|
183
|
+
## Roadmap
|
|
184
|
+
|
|
185
|
+
- React Native renderers (v1.1.0)
|
|
186
|
+
- Vue/Svelte adapter packages
|
|
187
|
+
- Custom detector plugins
|
|
188
|
+
- Confidence scores on classification
|
|
189
|
+
|
|
190
|
+
## License
|
|
191
|
+
|
|
192
|
+
MIT - Sagar Kalra / AutoPriseAI
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { SemanticBlock } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Classify a sanitized markdown string into semantic blocks.
|
|
4
|
+
*
|
|
5
|
+
* The classifier attempts to match the ENTIRE response to a single semantic
|
|
6
|
+
* type first (e.g., the whole response is a comparison). If no full-response
|
|
7
|
+
* match is found, it falls back to a default block.
|
|
8
|
+
*
|
|
9
|
+
* A verdict detector also runs and can capture a trailing section separately,
|
|
10
|
+
* resulting in [main content block, verdict block] when applicable.
|
|
11
|
+
*/
|
|
12
|
+
export declare function classify(markdown: string): SemanticBlock[];
|
|
13
|
+
//# sourceMappingURL=classifier.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"classifier.d.ts","sourceRoot":"","sources":["../../src/core/classifier.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,aAAa,EAQd,MAAM,YAAY,CAAC;AAobpB;;;;;;;;;GASG;AACH,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,aAAa,EAAE,CAuE1D"}
|