mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-16 16:30:15 +01:00
finish highlight.js styling (for chatgpt)
This commit is contained in:
parent
e95e22de15
commit
c58a9bbe93
12 changed files with 851 additions and 150 deletions
|
|
@ -36,9 +36,9 @@ Currently, this project is only functional with the `text-davinci-003` model.
|
|||
- [x] UI Error handling
|
||||
- [x] AI Model Selection
|
||||
- [x] Bing AI integration
|
||||
- [ ] Remember last selected model
|
||||
- [ ] AI model change handling (whether to pseudo-persist convos or start new convos within existing convo)
|
||||
- [x] Remember last selected model
|
||||
- [ ] Highlight.js for code blocks
|
||||
- [ ] AI model change handling (whether to pseudo-persist convos or start new convos within existing convo)
|
||||
- [ ] Server convo pagination (limit fetch and load more with 'show more' button)
|
||||
- [ ] Prompt Templates
|
||||
- [ ] Bing AI Styling (for suggested responses, convo end, etc.)
|
||||
|
|
|
|||
109
package-lock.json
generated
109
package-lock.json
generated
|
|
@ -28,7 +28,6 @@
|
|||
"openai": "^3.1.0",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-highlight": "^0.15.0",
|
||||
"react-redux": "^8.0.5",
|
||||
"react-textarea-autosize": "^8.4.0",
|
||||
"react-transition-group": "^4.4.5",
|
||||
|
|
@ -45,6 +44,7 @@
|
|||
"@babel/preset-env": "^7.20.2",
|
||||
"@babel/preset-react": "^7.18.6",
|
||||
"@babel/runtime": "^7.20.13",
|
||||
"@tailwindcss/typography": "^0.5.9",
|
||||
"autoprefixer": "^10.4.13",
|
||||
"babel-loader": "^9.1.2",
|
||||
"babel-plugin-root-import": "^6.6.0",
|
||||
|
|
@ -4096,6 +4096,34 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/typography": {
|
||||
"version": "0.5.9",
|
||||
"resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.9.tgz",
|
||||
"integrity": "sha512-t8Sg3DyynFysV9f4JDOVISGsjazNb48AeIYQwcL+Bsq5uf4RYL75C1giZ43KISjeDGBaTN3Kxh7Xj/vRSMJUUg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"lodash.castarray": "^4.4.0",
|
||||
"lodash.isplainobject": "^4.0.6",
|
||||
"lodash.merge": "^4.6.2",
|
||||
"postcss-selector-parser": "6.0.10"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"tailwindcss": ">=3.0.0 || insiders"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/typography/node_modules/postcss-selector-parser": {
|
||||
"version": "6.0.10",
|
||||
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz",
|
||||
"integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"cssesc": "^3.0.0",
|
||||
"util-deprecate": "^1.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/body-parser": {
|
||||
"version": "1.19.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz",
|
||||
|
|
@ -9879,12 +9907,24 @@
|
|||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
|
||||
},
|
||||
"node_modules/lodash.castarray": {
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.castarray/-/lodash.castarray-4.4.0.tgz",
|
||||
"integrity": "sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/lodash.debounce": {
|
||||
"version": "4.0.8",
|
||||
"resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
|
||||
"integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/lodash.isplainobject": {
|
||||
"version": "4.0.6",
|
||||
"resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
|
||||
"integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/lodash.merge": {
|
||||
"version": "4.6.2",
|
||||
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
|
||||
|
|
@ -12221,22 +12261,6 @@
|
|||
"react": "^18.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-highlight": {
|
||||
"version": "0.15.0",
|
||||
"resolved": "https://registry.npmjs.org/react-highlight/-/react-highlight-0.15.0.tgz",
|
||||
"integrity": "sha512-5uV/b/N4Z421GSVVe05fz+OfTsJtFzx/fJBdafZyw4LS70XjIZwgEx3Lrkfc01W/RzZ2Dtfb0DApoaJFAIKBtA==",
|
||||
"dependencies": {
|
||||
"highlight.js": "^10.5.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-highlight/node_modules/highlight.js": {
|
||||
"version": "10.7.3",
|
||||
"resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz",
|
||||
"integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==",
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/react-is": {
|
||||
"version": "18.2.0",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
|
||||
|
|
@ -17948,6 +17972,30 @@
|
|||
"reselect": "^4.1.7"
|
||||
}
|
||||
},
|
||||
"@tailwindcss/typography": {
|
||||
"version": "0.5.9",
|
||||
"resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.9.tgz",
|
||||
"integrity": "sha512-t8Sg3DyynFysV9f4JDOVISGsjazNb48AeIYQwcL+Bsq5uf4RYL75C1giZ43KISjeDGBaTN3Kxh7Xj/vRSMJUUg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"lodash.castarray": "^4.4.0",
|
||||
"lodash.isplainobject": "^4.0.6",
|
||||
"lodash.merge": "^4.6.2",
|
||||
"postcss-selector-parser": "6.0.10"
|
||||
},
|
||||
"dependencies": {
|
||||
"postcss-selector-parser": {
|
||||
"version": "6.0.10",
|
||||
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz",
|
||||
"integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"cssesc": "^3.0.0",
|
||||
"util-deprecate": "^1.0.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"@types/body-parser": {
|
||||
"version": "1.19.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz",
|
||||
|
|
@ -22352,12 +22400,24 @@
|
|||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
|
||||
},
|
||||
"lodash.castarray": {
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.castarray/-/lodash.castarray-4.4.0.tgz",
|
||||
"integrity": "sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q==",
|
||||
"dev": true
|
||||
},
|
||||
"lodash.debounce": {
|
||||
"version": "4.0.8",
|
||||
"resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
|
||||
"integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==",
|
||||
"dev": true
|
||||
},
|
||||
"lodash.isplainobject": {
|
||||
"version": "4.0.6",
|
||||
"resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
|
||||
"integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==",
|
||||
"dev": true
|
||||
},
|
||||
"lodash.merge": {
|
||||
"version": "4.6.2",
|
||||
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
|
||||
|
|
@ -23916,21 +23976,6 @@
|
|||
"scheduler": "^0.23.0"
|
||||
}
|
||||
},
|
||||
"react-highlight": {
|
||||
"version": "0.15.0",
|
||||
"resolved": "https://registry.npmjs.org/react-highlight/-/react-highlight-0.15.0.tgz",
|
||||
"integrity": "sha512-5uV/b/N4Z421GSVVe05fz+OfTsJtFzx/fJBdafZyw4LS70XjIZwgEx3Lrkfc01W/RzZ2Dtfb0DApoaJFAIKBtA==",
|
||||
"requires": {
|
||||
"highlight.js": "^10.5.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"highlight.js": {
|
||||
"version": "10.7.3",
|
||||
"resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz",
|
||||
"integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"react-is": {
|
||||
"version": "18.2.0",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
|
||||
|
|
|
|||
|
|
@ -40,7 +40,6 @@
|
|||
"openai": "^3.1.0",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-highlight": "^0.15.0",
|
||||
"react-redux": "^8.0.5",
|
||||
"react-textarea-autosize": "^8.4.0",
|
||||
"react-transition-group": "^4.4.5",
|
||||
|
|
@ -57,6 +56,7 @@
|
|||
"@babel/preset-env": "^7.20.2",
|
||||
"@babel/preset-react": "^7.18.6",
|
||||
"@babel/runtime": "^7.20.13",
|
||||
"@tailwindcss/typography": "^0.5.9",
|
||||
"autoprefixer": "^10.4.13",
|
||||
"babel-loader": "^9.1.2",
|
||||
"babel-plugin-root-import": "^6.6.0",
|
||||
|
|
|
|||
|
|
@ -1 +1,71 @@
|
|||
pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{color:#abb2bf;background:#282c34}.hljs-comment,.hljs-quote{color:#5c6370;font-style:italic}.hljs-doctag,.hljs-formula,.hljs-keyword{color:#c678dd}.hljs-deletion,.hljs-name,.hljs-section,.hljs-selector-tag,.hljs-subst{color:#e06c75}.hljs-literal{color:#56b6c2}.hljs-addition,.hljs-attribute,.hljs-meta .hljs-string,.hljs-regexp,.hljs-string{color:#98c379}.hljs-attr,.hljs-number,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-pseudo,.hljs-template-variable,.hljs-type,.hljs-variable{color:#d19a66}.hljs-bullet,.hljs-link,.hljs-meta,.hljs-selector-id,.hljs-symbol,.hljs-title{color:#61aeee}.hljs-built_in,.hljs-class .hljs-title,.hljs-title.class_{color:#e6c07b}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}.hljs-link{text-decoration:underline}
|
||||
pre code.hljs {
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
padding: 1em;
|
||||
}
|
||||
code.hljs {
|
||||
padding: 3px 5px;
|
||||
}
|
||||
.hljs {
|
||||
color: #abb2bf;
|
||||
background: #282c34;
|
||||
}
|
||||
.hljs-comment,
|
||||
.hljs-quote {
|
||||
color: #5c6370;
|
||||
font-style: italic;
|
||||
}
|
||||
.hljs-doctag,
|
||||
.hljs-formula,
|
||||
.hljs-keyword {
|
||||
color: #c678dd;
|
||||
}
|
||||
.hljs-deletion,
|
||||
.hljs-name,
|
||||
.hljs-section,
|
||||
.hljs-selector-tag,
|
||||
.hljs-subst {
|
||||
color: #e06c75;
|
||||
}
|
||||
.hljs-literal {
|
||||
color: #56b6c2;
|
||||
}
|
||||
.hljs-addition,
|
||||
.hljs-attribute,
|
||||
.hljs-meta .hljs-string,
|
||||
.hljs-regexp,
|
||||
.hljs-string {
|
||||
color: #98c379;
|
||||
}
|
||||
.hljs-attr,
|
||||
.hljs-number,
|
||||
.hljs-selector-attr,
|
||||
.hljs-selector-class,
|
||||
.hljs-selector-pseudo,
|
||||
.hljs-template-variable,
|
||||
.hljs-type,
|
||||
.hljs-variable {
|
||||
color: #d19a66;
|
||||
}
|
||||
.hljs-bullet,
|
||||
.hljs-link,
|
||||
.hljs-meta,
|
||||
.hljs-selector-id,
|
||||
.hljs-symbol,
|
||||
.hljs-title {
|
||||
color: #61aeee;
|
||||
}
|
||||
.hljs-built_in,
|
||||
.hljs-class .hljs-title,
|
||||
.hljs-title.class_ {
|
||||
color: #e6c07b;
|
||||
}
|
||||
.hljs-emphasis {
|
||||
font-style: italic;
|
||||
}
|
||||
.hljs-strong {
|
||||
font-weight: 700;
|
||||
}
|
||||
.hljs-link {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,55 +0,0 @@
|
|||
import React from 'react';
|
||||
import Embed from './Embed';
|
||||
import hljs from 'highlight.js';
|
||||
import Highlight from 'react-highlight';
|
||||
|
||||
export default function CodeWrapper({ text }) {
|
||||
if (text.includes('```')) {
|
||||
const codeRegex = /(```[^`]+?```)/g;
|
||||
const inLineRegex = /(`[^`]+?`)/g;
|
||||
const parts = text.split(codeRegex);
|
||||
// console.log(parts);
|
||||
const codeParts = parts.map((part, i) => {
|
||||
if (part.match(codeRegex)) {
|
||||
return (
|
||||
<Embed
|
||||
key={i}
|
||||
language="javascript"
|
||||
>
|
||||
{hljs.highlightAuto(part.slice(1, -1)).value}
|
||||
{/* <Highlight className="!whitespace-pre">{part.slice(1, -1)}</Highlight> */}
|
||||
|
||||
</Embed>
|
||||
);
|
||||
} else if (part.match(inLineRegex)) {
|
||||
const innerParts = part.split(inLineRegex);
|
||||
return innerParts.map((part, i) => {
|
||||
if (part.match(inLineRegex)) {
|
||||
return <code key={i}>{part.slice(1, -1)}</code>;
|
||||
} else {
|
||||
return part;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
return part;
|
||||
}
|
||||
});
|
||||
|
||||
return <>{codeParts}</>; // return the wrapped text
|
||||
} else {
|
||||
const matchRegex = /(`[^`]+?`)/g;
|
||||
const parts = text.split(matchRegex);
|
||||
// console.log('parts', parts);
|
||||
|
||||
// map over the parts and wrap any text between tildes with <code> tags
|
||||
const codeParts = parts.map((part, i) => {
|
||||
if (part.match(matchRegex)) {
|
||||
return <code key={i}>{part.slice(1, -1)}</code>;
|
||||
} else {
|
||||
return part;
|
||||
}
|
||||
});
|
||||
|
||||
return <>{codeParts}</>; // return the wrapped text
|
||||
}
|
||||
}
|
||||
|
|
@ -4,8 +4,8 @@ import React from 'react';
|
|||
export default function Embed({ children, language = ''}) {
|
||||
return (
|
||||
<pre>
|
||||
<div className="mb-4 rounded-md bg-black">
|
||||
<div className="relative flex items-center bg-gray-800 px-4 py-2 font-sans text-xs text-gray-200">
|
||||
<div className="mb-2 rounded-md bg-black">
|
||||
<div className="relative flex items-center bg-gray-800 px-4 py-2 font-sans text-xs text-gray-200 rounded-tl-md rounded-tr-md">
|
||||
<span className="">{ language }</span>
|
||||
<button className="ml-auto flex gap-2">
|
||||
<svg
|
||||
|
|
@ -35,26 +35,6 @@ export default function Embed({ children, language = ''}) {
|
|||
</div>
|
||||
<div className="overflow-y-auto p-4">
|
||||
{ children }
|
||||
{/* <span className="hljs-keyword">export</span> <span className="hljs-keyword">default</span> <span className="hljs-keyword">function</span> <span className="hljs-title function_">CodeWrapper</span>(<span className="hljs-params">{ text }</span>) {
|
||||
<span className="hljs-keyword">const</span> matchRegex = <span className="hljs-regexp">/(`[^`]+?`)/g</span>; <span className="hljs-comment">// regex to match backticks and text between them</span>
|
||||
<span className="hljs-keyword">const</span> parts = text.<span className="hljs-title function_">split</span>(matchRegex);
|
||||
<span className="hljs-variable language_">console</span>.<span className="hljs-title function_">log</span>(<span className="hljs-string">'parts'</span>, parts);
|
||||
|
||||
<span className="hljs-comment">// map over the parts and wrap any backticked text with <code> tags</span>
|
||||
<span className="hljs-keyword">const</span> codeParts = parts.<span className="hljs-title function_">map</span>(<span className="hljs-function">(<span className="hljs-params">part, index</span>) =></span> {
|
||||
<span className="hljs-keyword">if</span> (part.<span className="hljs-title function_">match</span>(matchRegex)) {
|
||||
<>
|
||||
<span className="hljs-keyword">return</span> <span className="xml"><span className="hljs-tag"><<span className="hljs-name">code</span> <span className="hljs-attr">key</span>=<span className="hljs-string">{index}</span>></span>{part}<span className="hljs-tag"></<span className="hljs-name">code</span>></span></span>;
|
||||
</>
|
||||
} <span className="hljs-keyword">else</span> {
|
||||
<>
|
||||
<span className="hljs-keyword">return</span> part.<span className="hljs-title function_">trim</span>(); <span className="hljs-comment">// remove leading/trailing whitespace from non-backticked text</span>
|
||||
</>
|
||||
}
|
||||
});
|
||||
|
||||
<span className="hljs-keyword">return</span> <span className="xml"><span className="hljs-tag"><></span>{codeParts}<span className="hljs-tag"></></span></span>; <span className="hljs-comment">// return the wrapped text</span>
|
||||
} */}
|
||||
</div>
|
||||
</div>
|
||||
</pre>
|
||||
|
|
|
|||
16
src/components/Messages/Highlight.jsx
Normal file
16
src/components/Messages/Highlight.jsx
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
import React, { useState, useEffect } from 'react';
|
||||
import hljs from 'highlight.js';
|
||||
|
||||
export default function Highlight({language, code}) {
|
||||
const [highlightedCode, setHighlightedCode] = useState(code);
|
||||
|
||||
useEffect(() => {
|
||||
setHighlightedCode(hljs.highlight(code, { language }).value);
|
||||
}, [code, language]);
|
||||
|
||||
return (
|
||||
<pre>
|
||||
<code className={`language-${language}`} dangerouslySetInnerHTML={{__html: highlightedCode}}/>
|
||||
</pre>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useState, useEffect } from 'react';
|
||||
import CodeWrapper from './CodeWrapper';
|
||||
import TextWrapper from './TextWrapper';
|
||||
import { useSelector } from 'react-redux';
|
||||
import GPTIcon from '../svg/GPTIcon';
|
||||
import BingIcon from '../svg/BingIcon';
|
||||
|
|
@ -13,7 +13,8 @@ export default function Message({
|
|||
}) {
|
||||
const { isSubmitting } = useSelector((state) => state.submit);
|
||||
const [abortScroll, setAbort] = useState(false);
|
||||
const blinker = isSubmitting && last && sender.toLowerCase() !== 'user';
|
||||
const notUser = sender.toLowerCase() !== 'user';
|
||||
const blinker = isSubmitting && last && notUser;
|
||||
|
||||
useEffect(() => {
|
||||
if (blinker && !abortScroll) {
|
||||
|
|
@ -34,15 +35,12 @@ export default function Message({
|
|||
'w-full border-b border-black/10 dark:border-gray-900/50 text-gray-800 dark:text-gray-100 group dark:bg-gray-800'
|
||||
};
|
||||
|
||||
if (sender.toLowerCase() !== 'user') {
|
||||
props.className =
|
||||
'w-full border-b border-black/10 dark:border-gray-900/50 text-gray-800 dark:text-gray-100 group bg-gray-100 dark:bg-[#444654]';
|
||||
}
|
||||
|
||||
let icon = `${sender}:`;
|
||||
const isGPT = sender === 'chatgpt' || sender === 'davinci' || sender === 'GPT';
|
||||
|
||||
if (sender.toLowerCase() !== 'user') {
|
||||
if (notUser) {
|
||||
props.className =
|
||||
'w-full border-b border-black/10 dark:border-gray-900/50 text-gray-800 dark:text-gray-100 group bg-gray-100 dark:bg-[#444654]';
|
||||
icon = (
|
||||
<div
|
||||
style={isGPT ? { backgroundColor: 'rgb(16, 163, 127)' } : {}}
|
||||
|
|
@ -53,7 +51,7 @@ export default function Message({
|
|||
);
|
||||
}
|
||||
|
||||
const wrapText = (text) => <CodeWrapper text={text} />;
|
||||
const wrapText = (text) => <TextWrapper text={text} />;
|
||||
|
||||
return (
|
||||
<div
|
||||
|
|
@ -67,13 +65,13 @@ export default function Message({
|
|||
{error ? (
|
||||
<div className="flex flex min-h-[20px] flex-row flex-col items-start gap-4 gap-2 whitespace-pre-wrap text-red-500">
|
||||
<div className="rounded-md border border-red-500 bg-red-500/10 py-2 px-3 text-sm text-gray-600 dark:text-gray-100">
|
||||
{wrapText(text)}
|
||||
{text}
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex min-h-[20px] flex-col items-start gap-4 whitespace-pre-wrap">
|
||||
<div className="markdown prose dark:prose-invert light w-full break-words">
|
||||
{wrapText(text)}
|
||||
{notUser ? wrapText(text) : text}
|
||||
{blinker && <span className="result-streaming">█</span>}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
87
src/components/Messages/TextWrapper.jsx
Normal file
87
src/components/Messages/TextWrapper.jsx
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
import React from 'react';
|
||||
import Embed from './Embed';
|
||||
import Highlight from './Highlight';
|
||||
import regexSplit from '~/utils/regexSplit';
|
||||
// const codeRegex = /(```[^`]+?```)/g;
|
||||
const codeRegex = /(```[\s\S]*?```)/g;
|
||||
const inLineRegex = /(`[^`]+?`)/g;
|
||||
const matchRegex = /(`[^`]+?`)/g;
|
||||
const languageMatch = /^```(\w+)/;
|
||||
const newLineMatch = /^```(\n+)/;
|
||||
const languages = [
|
||||
'java',
|
||||
'c',
|
||||
'python',
|
||||
'c++',
|
||||
'javascript',
|
||||
'csharp',
|
||||
'php',
|
||||
'typescript',
|
||||
'swift',
|
||||
'objectivec',
|
||||
'sql',
|
||||
'r',
|
||||
'kotlin',
|
||||
'ruby',
|
||||
'go',
|
||||
'x86asm',
|
||||
'matlab',
|
||||
'perl',
|
||||
'pascal'
|
||||
];
|
||||
|
||||
const inLineWrap = (parts) =>
|
||||
parts.map((part, i) => {
|
||||
if (part.match(matchRegex)) {
|
||||
return <code key={i}>{part.slice(1, -1)}</code>;
|
||||
} else {
|
||||
// return <p key={i}>{part}</p>;
|
||||
return part;
|
||||
}
|
||||
});
|
||||
|
||||
export default function CodeWrapper({ text }) {
|
||||
if (text.includes('```')) {
|
||||
// const parts = text.split(codeRegex);
|
||||
const parts = regexSplit(text);
|
||||
console.log(parts);
|
||||
const codeParts = parts.map((part, i) => {
|
||||
if (part.match(codeRegex)) {
|
||||
let language = 'javascript';
|
||||
|
||||
if (part.match(languageMatch)) {
|
||||
language = part.match(languageMatch)[1].toLowerCase();
|
||||
const validLanguage = languages.some((lang) => language === lang);
|
||||
part = validLanguage ? part.replace(languageMatch, '```') : part;
|
||||
language = validLanguage ? language : 'javascript';
|
||||
}
|
||||
|
||||
part = part.replace(newLineMatch, '```');
|
||||
|
||||
return (
|
||||
<Embed
|
||||
key={i}
|
||||
language={language}
|
||||
>
|
||||
<Highlight
|
||||
code={part.slice(3, -3)}
|
||||
language={language}
|
||||
/>
|
||||
</Embed>
|
||||
);
|
||||
} else if (part.match(inLineRegex)) {
|
||||
const innerParts = part.split(inLineRegex);
|
||||
return inLineWrap(innerParts);
|
||||
} else {
|
||||
return part;
|
||||
}
|
||||
});
|
||||
|
||||
return <>{codeParts}</>; // return the wrapped text
|
||||
} else {
|
||||
// map over the parts and wrap any text between tildes with <code> tags
|
||||
const parts = text.split(matchRegex);
|
||||
const codeParts = inLineWrap(parts);
|
||||
return <>{codeParts}</>; // return the wrapped text
|
||||
}
|
||||
}
|
||||
584
src/style.css
584
src/style.css
|
|
@ -6,28 +6,6 @@
|
|||
box-sizing: border-box;
|
||||
outline: 1px solid limegreen !important;
|
||||
} */
|
||||
.prose :where(code):not(:where([class~="not-prose"] *)) {
|
||||
color: var(--tw-prose-code);
|
||||
font-size: .875em;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.prose :where(code):not(:where([class~="not-prose"] *))::before {
|
||||
content: "`";
|
||||
}
|
||||
|
||||
.prose :where(code):not(:where([class~="not-prose"] *))::after {
|
||||
content: "`";
|
||||
}
|
||||
|
||||
code, pre {
|
||||
font-family: Söhne Mono,Monaco,Andale Mono,Ubuntu Mono,monospace !important;
|
||||
}
|
||||
|
||||
code, kbd, pre, samp {
|
||||
font-family: Söhne Mono,Monaco,Andale Mono,Ubuntu Mono,monospace;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
.scroll-down-enter {
|
||||
opacity: 0;
|
||||
|
|
@ -101,6 +79,568 @@ code, kbd, pre, samp {
|
|||
}
|
||||
}
|
||||
|
||||
.prose {
|
||||
color:var(--tw-prose-body);
|
||||
max-width:65ch
|
||||
}
|
||||
.prose :where([class~=lead]):not(:where([class~=not-prose] *)) {
|
||||
color:var(--tw-prose-lead);
|
||||
font-size:1.25em;
|
||||
line-height:1.6;
|
||||
margin-bottom:1.2em;
|
||||
margin-top:1.2em
|
||||
}
|
||||
.prose :where(a):not(:where([class~=not-prose] *)) {
|
||||
color:var(--tw-prose-links);
|
||||
font-weight:500;
|
||||
text-decoration:underline
|
||||
}
|
||||
.prose :where(strong):not(:where([class~=not-prose] *)) {
|
||||
color:var(--tw-prose-bold);
|
||||
font-weight:600
|
||||
}
|
||||
.prose :where(a strong):not(:where([class~=not-prose] *)) {
|
||||
color:inherit
|
||||
}
|
||||
.prose :where(blockquote strong):not(:where([class~=not-prose] *)) {
|
||||
color:inherit
|
||||
}
|
||||
.prose :where(thead th strong):not(:where([class~=not-prose] *)) {
|
||||
color:inherit
|
||||
}
|
||||
.prose :where(ol):not(:where([class~=not-prose] *)) {
|
||||
list-style-type:decimal;
|
||||
margin-bottom:1.25em;
|
||||
margin-top:1.25em;
|
||||
padding-left:1.625em
|
||||
}
|
||||
.prose :where(ol[type=A]):not(:where([class~=not-prose] *)) {
|
||||
list-style-type:upper-alpha
|
||||
}
|
||||
.prose :where(ol[type=a]):not(:where([class~=not-prose] *)) {
|
||||
list-style-type:lower-alpha
|
||||
}
|
||||
.prose :where(ol[type=A s]):not(:where([class~=not-prose] *)) {
|
||||
list-style-type:upper-alpha
|
||||
}
|
||||
.prose :where(ol[type=a s]):not(:where([class~=not-prose] *)) {
|
||||
list-style-type:lower-alpha
|
||||
}
|
||||
.prose :where(ol[type=I]):not(:where([class~=not-prose] *)) {
|
||||
list-style-type:upper-roman
|
||||
}
|
||||
.prose :where(ol[type=i]):not(:where([class~=not-prose] *)) {
|
||||
list-style-type:lower-roman
|
||||
}
|
||||
.prose :where(ol[type=I s]):not(:where([class~=not-prose] *)) {
|
||||
list-style-type:upper-roman
|
||||
}
|
||||
.prose :where(ol[type=i s]):not(:where([class~=not-prose] *)) {
|
||||
list-style-type:lower-roman
|
||||
}
|
||||
.prose :where(ol[type="1"]):not(:where([class~=not-prose] *)) {
|
||||
list-style-type:decimal
|
||||
}
|
||||
.prose :where(ul):not(:where([class~=not-prose] *)) {
|
||||
list-style-type:disc;
|
||||
margin-bottom:1.25em;
|
||||
margin-top:1.25em;
|
||||
padding-left:1.625em
|
||||
}
|
||||
.prose :where(ol>li):not(:where([class~=not-prose] *))::marker {
|
||||
color:var(--tw-prose-counters);
|
||||
font-weight:400
|
||||
}
|
||||
.prose :where(ul>li):not(:where([class~=not-prose] *))::marker {
|
||||
color:var(--tw-prose-bullets)
|
||||
}
|
||||
.prose :where(hr):not(:where([class~=not-prose] *)) {
|
||||
border-color:var(--tw-prose-hr);
|
||||
border-top-width:1px;
|
||||
margin-bottom:3em;
|
||||
margin-top:3em
|
||||
}
|
||||
.prose :where(blockquote):not(:where([class~=not-prose] *)) {
|
||||
border-left-color:var(--tw-prose-quote-borders);
|
||||
border-left-width:.25rem;
|
||||
color:var(--tw-prose-quotes);
|
||||
font-style:italic;
|
||||
font-style:normal;
|
||||
font-weight:500;
|
||||
margin-bottom:1.6em;
|
||||
margin-top:1.6em;
|
||||
padding-left:1em;
|
||||
quotes:"\201C""\201D""\2018""\2019"
|
||||
}
|
||||
.prose :where(blockquote p:first-of-type):not(:where([class~=not-prose] *)):before {
|
||||
content:open-quote
|
||||
}
|
||||
.prose :where(blockquote p:last-of-type):not(:where([class~=not-prose] *)):after {
|
||||
content:close-quote
|
||||
}
|
||||
.prose :where(h1):not(:where([class~=not-prose] *)) {
|
||||
color:var(--tw-prose-headings);
|
||||
font-size:2.25em;
|
||||
font-weight:800;
|
||||
line-height:1.1111111;
|
||||
margin-bottom:.8888889em;
|
||||
margin-top:0
|
||||
}
|
||||
.prose :where(h1 strong):not(:where([class~=not-prose] *)) {
|
||||
color:inherit;
|
||||
font-weight:900
|
||||
}
|
||||
.prose :where(h2):not(:where([class~=not-prose] *)) {
|
||||
color:var(--tw-prose-headings);
|
||||
font-size:1.5em;
|
||||
font-weight:700;
|
||||
line-height:1.3333333;
|
||||
margin-bottom:1em;
|
||||
margin-top:2em
|
||||
}
|
||||
.prose :where(h2 strong):not(:where([class~=not-prose] *)) {
|
||||
color:inherit;
|
||||
font-weight:800
|
||||
}
|
||||
.prose :where(h3):not(:where([class~=not-prose] *)) {
|
||||
color:var(--tw-prose-headings);
|
||||
font-size:1.25em;
|
||||
font-weight:600;
|
||||
line-height:1.6;
|
||||
margin-bottom:.6em;
|
||||
margin-top:1.6em
|
||||
}
|
||||
.prose :where(h3 strong):not(:where([class~=not-prose] *)) {
|
||||
color:inherit;
|
||||
font-weight:700
|
||||
}
|
||||
.prose :where(h4):not(:where([class~=not-prose] *)) {
|
||||
color:var(--tw-prose-headings);
|
||||
font-weight:600;
|
||||
line-height:1.5;
|
||||
margin-bottom:.5em;
|
||||
margin-top:1.5em
|
||||
}
|
||||
.prose :where(h4 strong):not(:where([class~=not-prose] *)) {
|
||||
color:inherit;
|
||||
font-weight:700
|
||||
}
|
||||
.prose :where(img):not(:where([class~=not-prose] *)) {
|
||||
margin-bottom:2em;
|
||||
margin-top:2em
|
||||
}
|
||||
.prose :where(figure>*):not(:where([class~=not-prose] *)) {
|
||||
margin-bottom:0;
|
||||
margin-top:0
|
||||
}
|
||||
.prose :where(figcaption):not(:where([class~=not-prose] *)) {
|
||||
color:var(--tw-prose-captions);
|
||||
font-size:.875em;
|
||||
line-height:1.4285714;
|
||||
margin-top:.8571429em
|
||||
}
|
||||
.prose :where(code):not(:where([class~=not-prose] *)) {
|
||||
color:var(--tw-prose-code);
|
||||
font-size:.875em;
|
||||
font-weight:600
|
||||
}
|
||||
.prose :where(code):not(:where([class~=not-prose] *)):before {
|
||||
content:"`"
|
||||
}
|
||||
.prose :where(code):not(:where([class~=not-prose] *)):after {
|
||||
content:"`"
|
||||
}
|
||||
.prose :where(a code):not(:where([class~=not-prose] *)) {
|
||||
color:inherit
|
||||
}
|
||||
.prose :where(h1 code):not(:where([class~=not-prose] *)) {
|
||||
color:inherit
|
||||
}
|
||||
.prose :where(h2 code):not(:where([class~=not-prose] *)) {
|
||||
color:inherit;
|
||||
font-size:.875em
|
||||
}
|
||||
.prose :where(h3 code):not(:where([class~=not-prose] *)) {
|
||||
color:inherit;
|
||||
font-size:.9em
|
||||
}
|
||||
.prose :where(h4 code):not(:where([class~=not-prose] *)) {
|
||||
color:inherit
|
||||
}
|
||||
.prose :where(blockquote code):not(:where([class~=not-prose] *)) {
|
||||
color:inherit
|
||||
}
|
||||
.prose :where(thead th code):not(:where([class~=not-prose] *)) {
|
||||
color:inherit
|
||||
}
|
||||
.prose :where(pre):not(:where([class~=not-prose] *)) {
|
||||
background-color:transparent;
|
||||
border-radius:.375rem;
|
||||
color:currentColor;
|
||||
font-size:.875em;
|
||||
font-weight:400;
|
||||
line-height:1.7142857;
|
||||
margin:0;
|
||||
overflow-x:auto;
|
||||
padding:0
|
||||
}
|
||||
.prose :where(pre code):not(:where([class~=not-prose] *)) {
|
||||
background-color:transparent;
|
||||
border-radius:0;
|
||||
border-width:0;
|
||||
color:inherit;
|
||||
font-family:inherit;
|
||||
font-size:inherit;
|
||||
font-weight:inherit;
|
||||
line-height:inherit;
|
||||
padding:0
|
||||
}
|
||||
.prose :where(pre code):not(:where([class~=not-prose] *)):before {
|
||||
content:none
|
||||
}
|
||||
.prose :where(pre code):not(:where([class~=not-prose] *)):after {
|
||||
content:none
|
||||
}
|
||||
.prose :where(table):not(:where([class~=not-prose] *)) {
|
||||
font-size:.875em;
|
||||
line-height:1.7142857;
|
||||
margin-bottom:2em;
|
||||
margin-top:2em;
|
||||
table-layout:auto;
|
||||
text-align:left;
|
||||
width:100%
|
||||
}
|
||||
.prose :where(thead):not(:where([class~=not-prose] *)) {
|
||||
border-bottom-color:var(--tw-prose-th-borders);
|
||||
border-bottom-width:1px
|
||||
}
|
||||
.prose :where(thead th):not(:where([class~=not-prose] *)) {
|
||||
color:var(--tw-prose-headings);
|
||||
font-weight:600;
|
||||
padding-bottom:.5714286em;
|
||||
padding-left:.5714286em;
|
||||
padding-right:.5714286em;
|
||||
vertical-align:bottom
|
||||
}
|
||||
.prose :where(tbody tr):not(:where([class~=not-prose] *)) {
|
||||
border-bottom-color:var(--tw-prose-td-borders);
|
||||
border-bottom-width:1px
|
||||
}
|
||||
.prose :where(tbody tr:last-child):not(:where([class~=not-prose] *)) {
|
||||
border-bottom-width:0
|
||||
}
|
||||
.prose :where(tbody td):not(:where([class~=not-prose] *)) {
|
||||
vertical-align:baseline
|
||||
}
|
||||
.prose :where(tfoot):not(:where([class~=not-prose] *)) {
|
||||
border-top-color:var(--tw-prose-th-borders);
|
||||
border-top-width:1px
|
||||
}
|
||||
.prose :where(tfoot td):not(:where([class~=not-prose] *)) {
|
||||
vertical-align:top
|
||||
}
|
||||
.prose {
|
||||
--tw-prose-body:#374151;
|
||||
--tw-prose-headings:#111827;
|
||||
--tw-prose-lead:#4b5563;
|
||||
--tw-prose-links:#111827;
|
||||
--tw-prose-bold:#111827;
|
||||
--tw-prose-counters:#6b7280;
|
||||
--tw-prose-bullets:#d1d5db;
|
||||
--tw-prose-hr:#e5e7eb;
|
||||
--tw-prose-quotes:#111827;
|
||||
--tw-prose-quote-borders:#e5e7eb;
|
||||
--tw-prose-captions:#6b7280;
|
||||
--tw-prose-code:#111827;
|
||||
--tw-prose-pre-code:#e5e7eb;
|
||||
--tw-prose-pre-bg:#1f2937;
|
||||
--tw-prose-th-borders:#d1d5db;
|
||||
--tw-prose-td-borders:#e5e7eb;
|
||||
--tw-prose-invert-body:#d1d5db;
|
||||
--tw-prose-invert-headings:#fff;
|
||||
--tw-prose-invert-lead:#9ca3af;
|
||||
--tw-prose-invert-links:#fff;
|
||||
--tw-prose-invert-bold:#fff;
|
||||
--tw-prose-invert-counters:#9ca3af;
|
||||
--tw-prose-invert-bullets:#4b5563;
|
||||
--tw-prose-invert-hr:#374151;
|
||||
--tw-prose-invert-quotes:#f3f4f6;
|
||||
--tw-prose-invert-quote-borders:#374151;
|
||||
--tw-prose-invert-captions:#9ca3af;
|
||||
--tw-prose-invert-code:#fff;
|
||||
--tw-prose-invert-pre-code:#d1d5db;
|
||||
--tw-prose-invert-pre-bg:rgba(0,0,0,.5);
|
||||
--tw-prose-invert-th-borders:#4b5563;
|
||||
--tw-prose-invert-td-borders:#374151;
|
||||
font-size:1rem;
|
||||
line-height:1.75
|
||||
}
|
||||
.prose :where(p):not(:where([class~=not-prose] *)) {
|
||||
margin-bottom:1.25em;
|
||||
margin-top:1.25em
|
||||
}
|
||||
.prose :where(video):not(:where([class~=not-prose] *)) {
|
||||
margin-bottom:2em;
|
||||
margin-top:2em
|
||||
}
|
||||
.prose :where(figure):not(:where([class~=not-prose] *)) {
|
||||
margin-bottom:2em;
|
||||
margin-top:2em
|
||||
}
|
||||
.prose :where(li):not(:where([class~=not-prose] *)) {
|
||||
margin-bottom:.5em;
|
||||
margin-top:.5em
|
||||
}
|
||||
.prose :where(ol>li):not(:where([class~=not-prose] *)) {
|
||||
padding-left:.375em
|
||||
}
|
||||
.prose :where(ul>li):not(:where([class~=not-prose] *)) {
|
||||
padding-left:.375em
|
||||
}
|
||||
.prose :where(.prose>ul>li p):not(:where([class~=not-prose] *)) {
|
||||
margin-bottom:.75em;
|
||||
margin-top:.75em
|
||||
}
|
||||
.prose :where(.prose>ul>li>:first-child):not(:where([class~=not-prose] *)) {
|
||||
margin-top:1.25em
|
||||
}
|
||||
.prose :where(.prose>ul>li>:last-child):not(:where([class~=not-prose] *)) {
|
||||
margin-bottom:1.25em
|
||||
}
|
||||
.prose :where(.prose>ol>li>:first-child):not(:where([class~=not-prose] *)) {
|
||||
margin-top:1.25em
|
||||
}
|
||||
.prose :where(.prose>ol>li>:last-child):not(:where([class~=not-prose] *)) {
|
||||
margin-bottom:1.25em
|
||||
}
|
||||
.prose :where(ul ul,
|
||||
ul ol,
|
||||
ol ul,
|
||||
ol ol):not(:where([class~=not-prose] *)) {
|
||||
margin-bottom:.75em;
|
||||
margin-top:.75em
|
||||
}
|
||||
.prose :where(hr+*):not(:where([class~=not-prose] *)) {
|
||||
margin-top:0
|
||||
}
|
||||
.prose :where(h2+*):not(:where([class~=not-prose] *)) {
|
||||
margin-top:0
|
||||
}
|
||||
.prose :where(h3+*):not(:where([class~=not-prose] *)) {
|
||||
margin-top:0
|
||||
}
|
||||
.prose :where(h4+*):not(:where([class~=not-prose] *)) {
|
||||
margin-top:0
|
||||
}
|
||||
.prose :where(thead th:first-child):not(:where([class~=not-prose] *)) {
|
||||
padding-left:0
|
||||
}
|
||||
.prose :where(thead th:last-child):not(:where([class~=not-prose] *)) {
|
||||
padding-right:0
|
||||
}
|
||||
.prose :where(tbody td,
|
||||
tfoot td):not(:where([class~=not-prose] *)) {
|
||||
padding:.5714286em
|
||||
}
|
||||
.prose :where(tbody td:first-child,
|
||||
tfoot td:first-child):not(:where([class~=not-prose] *)) {
|
||||
padding-left:0
|
||||
}
|
||||
.prose :where(tbody td:last-child,
|
||||
tfoot td:last-child):not(:where([class~=not-prose] *)) {
|
||||
padding-right:0
|
||||
}
|
||||
.prose :where(.prose>:first-child):not(:where([class~=not-prose] *)) {
|
||||
margin-top:0
|
||||
}
|
||||
.prose :where(.prose>:last-child):not(:where([class~=not-prose] *)) {
|
||||
margin-bottom:0
|
||||
}
|
||||
.prose-sm :where(.prose>ul>li p):not(:where([class~=not-prose] *)) {
|
||||
margin-bottom:.5714286em;
|
||||
margin-top:.5714286em
|
||||
}
|
||||
.prose-sm :where(.prose>ul>li>:first-child):not(:where([class~=not-prose] *)) {
|
||||
margin-top:1.1428571em
|
||||
}
|
||||
.prose-sm :where(.prose>ul>li>:last-child):not(:where([class~=not-prose] *)) {
|
||||
margin-bottom:1.1428571em
|
||||
}
|
||||
.prose-sm :where(.prose>ol>li>:first-child):not(:where([class~=not-prose] *)) {
|
||||
margin-top:1.1428571em
|
||||
}
|
||||
.prose-sm :where(.prose>ol>li>:last-child):not(:where([class~=not-prose] *)) {
|
||||
margin-bottom:1.1428571em
|
||||
}
|
||||
.prose-sm :where(.prose>:first-child):not(:where([class~=not-prose] *)) {
|
||||
margin-top:0
|
||||
}
|
||||
.prose-sm :where(.prose>:last-child):not(:where([class~=not-prose] *)) {
|
||||
margin-bottom:0
|
||||
}
|
||||
.prose-base :where(.prose>ul>li p):not(:where([class~=not-prose] *)) {
|
||||
margin-bottom:.75em;
|
||||
margin-top:.75em
|
||||
}
|
||||
.prose-base :where(.prose>ul>li>:first-child):not(:where([class~=not-prose] *)) {
|
||||
margin-top:1.25em
|
||||
}
|
||||
.prose-base :where(.prose>ul>li>:last-child):not(:where([class~=not-prose] *)) {
|
||||
margin-bottom:1.25em
|
||||
}
|
||||
.prose-base :where(.prose>ol>li>:first-child):not(:where([class~=not-prose] *)) {
|
||||
margin-top:1.25em
|
||||
}
|
||||
.prose-base :where(.prose>ol>li>:last-child):not(:where([class~=not-prose] *)) {
|
||||
margin-bottom:1.25em
|
||||
}
|
||||
.prose-base :where(.prose>:first-child):not(:where([class~=not-prose] *)) {
|
||||
margin-top:0
|
||||
}
|
||||
.prose-base :where(.prose>:last-child):not(:where([class~=not-prose] *)) {
|
||||
margin-bottom:0
|
||||
}
|
||||
.prose-lg :where(.prose>ul>li p):not(:where([class~=not-prose] *)) {
|
||||
margin-bottom:.8888889em;
|
||||
margin-top:.8888889em
|
||||
}
|
||||
.prose-lg :where(.prose>ul>li>:first-child):not(:where([class~=not-prose] *)) {
|
||||
margin-top:1.3333333em
|
||||
}
|
||||
.prose-lg :where(.prose>ul>li>:last-child):not(:where([class~=not-prose] *)) {
|
||||
margin-bottom:1.3333333em
|
||||
}
|
||||
.prose-lg :where(.prose>ol>li>:first-child):not(:where([class~=not-prose] *)) {
|
||||
margin-top:1.3333333em
|
||||
}
|
||||
.prose-lg :where(.prose>ol>li>:last-child):not(:where([class~=not-prose] *)) {
|
||||
margin-bottom:1.3333333em
|
||||
}
|
||||
.prose-lg :where(.prose>:first-child):not(:where([class~=not-prose] *)) {
|
||||
margin-top:0
|
||||
}
|
||||
.prose-lg :where(.prose>:last-child):not(:where([class~=not-prose] *)) {
|
||||
margin-bottom:0
|
||||
}
|
||||
.prose-xl :where(.prose>ul>li p):not(:where([class~=not-prose] *)) {
|
||||
margin-bottom:.8em;
|
||||
margin-top:.8em
|
||||
}
|
||||
.prose-xl :where(.prose>ul>li>:first-child):not(:where([class~=not-prose] *)) {
|
||||
margin-top:1.2em
|
||||
}
|
||||
.prose-xl :where(.prose>ul>li>:last-child):not(:where([class~=not-prose] *)) {
|
||||
margin-bottom:1.2em
|
||||
}
|
||||
.prose-xl :where(.prose>ol>li>:first-child):not(:where([class~=not-prose] *)) {
|
||||
margin-top:1.2em
|
||||
}
|
||||
.prose-xl :where(.prose>ol>li>:last-child):not(:where([class~=not-prose] *)) {
|
||||
margin-bottom:1.2em
|
||||
}
|
||||
.prose-xl :where(.prose>:first-child):not(:where([class~=not-prose] *)) {
|
||||
margin-top:0
|
||||
}
|
||||
.prose-xl :where(.prose>:last-child):not(:where([class~=not-prose] *)) {
|
||||
margin-bottom:0
|
||||
}
|
||||
.prose-2xl :where(.prose>ul>li p):not(:where([class~=not-prose] *)) {
|
||||
margin-bottom:.8333333em;
|
||||
margin-top:.8333333em
|
||||
}
|
||||
.prose-2xl :where(.prose>ul>li>:first-child):not(:where([class~=not-prose] *)) {
|
||||
margin-top:1.3333333em
|
||||
}
|
||||
.prose-2xl :where(.prose>ul>li>:last-child):not(:where([class~=not-prose] *)) {
|
||||
margin-bottom:1.3333333em
|
||||
}
|
||||
.prose-2xl :where(.prose>ol>li>:first-child):not(:where([class~=not-prose] *)) {
|
||||
margin-top:1.3333333em
|
||||
}
|
||||
.prose-2xl :where(.prose>ol>li>:last-child):not(:where([class~=not-prose] *)) {
|
||||
margin-bottom:1.3333333em
|
||||
}
|
||||
.prose-2xl :where(.prose>:first-child):not(:where([class~=not-prose] *)) {
|
||||
margin-top:0
|
||||
}
|
||||
.prose-2xl :where(.prose>:last-child):not(:where([class~=not-prose] *)) {
|
||||
margin-bottom:0
|
||||
}
|
||||
|
||||
code,
|
||||
pre {
|
||||
font-family: Söhne Mono, Monaco, Andale Mono, Ubuntu Mono, monospace !important;
|
||||
}
|
||||
code[class='language-plaintext'] {
|
||||
white-space: pre-line;
|
||||
}
|
||||
code.hljs,
|
||||
code[class*='language-'],
|
||||
pre[class*='language-'] {
|
||||
word-wrap: normal;
|
||||
background: none;
|
||||
color: #fff;
|
||||
-webkit-hyphens: none;
|
||||
hyphens: none;
|
||||
font-size: .85rem;
|
||||
line-height: 1.5;
|
||||
tab-size: 4;
|
||||
text-align: left;
|
||||
white-space: pre;
|
||||
word-break: normal;
|
||||
word-spacing: normal;
|
||||
}
|
||||
pre[class*='language-'] {
|
||||
border-radius: 0.3em;
|
||||
overflow: auto;
|
||||
}
|
||||
:not(pre) > code.hljs,
|
||||
:not(pre) > code[class*='language-'] {
|
||||
border-radius: 0.3em;
|
||||
padding: 0.1em;
|
||||
white-space: normal;
|
||||
}
|
||||
.hljs-comment {
|
||||
color: hsla(0, 0%, 100%, 0.5);
|
||||
}
|
||||
.hljs-meta {
|
||||
color: hsla(0, 0%, 100%, 0.6);
|
||||
}
|
||||
.hljs-built_in,
|
||||
.hljs-class .hljs-title {
|
||||
color: #e9950c;
|
||||
}
|
||||
.hljs-doctag,
|
||||
.hljs-formula,
|
||||
.hljs-keyword,
|
||||
.hljs-literal {
|
||||
color: #2e95d3;
|
||||
}
|
||||
.hljs-addition,
|
||||
.hljs-attribute,
|
||||
.hljs-meta-string,
|
||||
.hljs-regexp,
|
||||
.hljs-string {
|
||||
color: #00a67d;
|
||||
}
|
||||
.hljs-attr,
|
||||
.hljs-number,
|
||||
.hljs-selector-attr,
|
||||
.hljs-selector-class,
|
||||
.hljs-selector-pseudo,
|
||||
.hljs-template-variable,
|
||||
.hljs-type,
|
||||
.hljs-variable {
|
||||
color: #df3079;
|
||||
}
|
||||
.hljs-bullet,
|
||||
.hljs-link,
|
||||
.hljs-selector-id,
|
||||
.hljs-symbol,
|
||||
.hljs-title {
|
||||
color: #f22c3d;
|
||||
}
|
||||
|
||||
.dark .dark\:md\:bg-vert-dark-gradient {
|
||||
background-image: linear-gradient(180deg, rgba(53, 55, 64, 0), #353740 58.85%);
|
||||
}
|
||||
|
|
|
|||
20
src/utils/regexSplit.js
Normal file
20
src/utils/regexSplit.js
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
// const string = 'Some text before\n```python\nThis is some `Python` code with ```backticks``` inside the enclosure\n```\nSome text after\n```javascript\nThis is some JavaScript code\n```\n';
|
||||
const regex = /```([^`\n]*?)\n([\s\S]*?)\n```/g;
|
||||
|
||||
export default function regexSplit(string) {
|
||||
const matches = [...string.matchAll(regex)];
|
||||
const output = [matches[0].input.slice(0, matches[0].index)];
|
||||
|
||||
for (let i = 0; i < matches.length; i++) {
|
||||
const [fullMatch, language, code] = matches[i];
|
||||
// const formattedCode = code.replace(/`+/g, '\\`');
|
||||
const formattedCode = code;
|
||||
output.push(`\`\`\`${language}\n${formattedCode}\n\`\`\``);
|
||||
if (i < matches.length - 1) {
|
||||
const nextText = string.slice(matches[i].index + fullMatch.length, matches[i + 1].index);
|
||||
output.push(nextText.trim());
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
|
@ -5,9 +5,6 @@ module.exports = {
|
|||
content: ['./src/**/*.{js,jsx,ts,tsx}'],
|
||||
// darkMode: 'class',
|
||||
darkMode: ['class'],
|
||||
theme: {
|
||||
extend: {}
|
||||
},
|
||||
theme: {
|
||||
extend: {
|
||||
// fontFamily: {
|
||||
|
|
@ -29,5 +26,8 @@ module.exports = {
|
|||
}
|
||||
}
|
||||
},
|
||||
plugins: [require('tailwindcss-animate')]
|
||||
plugins: [
|
||||
require('tailwindcss-animate'),
|
||||
// require('@tailwindcss/typography'),
|
||||
]
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue