Skip to content

Features/add js interpreter #355

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 6 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions src/lib/common/markdown/Markdown.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@
/** @type {boolean} */
export let scrollable = false;

const scrollbarId = uuidv4();

const scrollbarId = `markdown-scrollbar-${uuidv4()}`;
const options = {
scrollbars: {
visibility: 'auto',
Expand All @@ -42,7 +41,7 @@
});

function initScrollbar() {
const elem = document.querySelector(`#markdown-scrollbar-${scrollbarId}`);
const elem = document.querySelector(`#${scrollbarId}`);
if (elem) {
// @ts-ignore
const scrollbar = OverlayScrollbars(elem, options);
Expand All @@ -65,7 +64,7 @@
</script>

<div
id={`markdown-scrollbar-${scrollbarId}`}
id={`${scrollbarId}`}
class={`markdown-container markdown-lite ${containerClasses || 'text-white'}`}
style={`${containerStyles}`}
>
Expand Down
3 changes: 2 additions & 1 deletion src/lib/helpers/enums.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ const richType = {
Button: 'button_template',
MultiSelect: 'multi-select_template',
Generic: 'generic_template',
Upload: 'upload_template'
Upload: 'upload_template',
JsCode: 'js_code',
}
export const RichType = Object.freeze(richType);

Expand Down
2 changes: 1 addition & 1 deletion src/lib/helpers/http.js
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ export function replaceNewLine(text) {
* @returns {string}
*/
export function replaceMarkdown(text) {
let res = text.replace(/#([\s]+)/g, '\\# ').replace(/[-|=]{3,}/g, '');
let res = text.replace(/#([\s]+)/g, '\\# ').replace(/[-|=]{3,}/g, '@@@');

let regex1 = new RegExp('\\*(.*)\\*', 'g');
let regex2 = new RegExp('\\*([\\*]+)\\*', 'g');
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<script>
import { onMount } from "svelte";
import { marked } from "marked";
import 'overlayscrollbars/overlayscrollbars.css';
import { OverlayScrollbars } from 'overlayscrollbars';
import { v4 as uuidv4 } from 'uuid';

/** @type {import('$conversationTypes').ChatResponseModel?} */
export let message;

/** @type {boolean} */
export let scrollable = false;

const scrollbarId = `js-interpreter-scrollbar-${uuidv4()}`;
const options = {
scrollbars: {
visibility: 'auto',
autoHide: 'move',
autoHideDelay: 100,
dragScroll: true,
clickScroll: false,
theme: 'os-theme-dark',
pointers: ['mouse', 'touch', 'pen']
}
};

onMount(() => {
if (scrollable) {
initScrollbar();
}

initCode();
});

function initScrollbar() {
const elem = document.querySelector(`#${scrollbarId}`);
if (elem) {
// @ts-ignore
const scrollbar = OverlayScrollbars(elem, options);
}
}

function initCode() {
try {
const text = message?.rich_content?.message?.text || message?.text || '';
const parsedText = marked.lexer(text);
// @ts-ignore
const codeText = parsedText.filter(x => !!x.text).map(x => x.text).join('');
loadScript(codeText);
} catch (error) {
console.error('Error parsing js code:', error);
}
}

/** @param {string} codeText */
function loadScript(codeText) {
const code = codeText.replace(/<script\b[^>]*>([\s\S]*?)<\/script>/gi, '$1');
const matchedSrcs = codeText.match(/<script\s+[^>]*src\s*=\s*["']([^"']+)["'][^>]*>/i);
if (matchedSrcs && matchedSrcs[1]) {
const curScripts = document.head.getElementsByTagName("script");
const found = Array.from(curScripts).find(x => x.src === matchedSrcs[1]);
if (found) {
found.remove();
}

const script = document.createElement('script');
script.src = matchedSrcs[1];
script.onload = () => eval(code);
document.head.appendChild(script);
} else {
eval(code);
}
}
</script>

<div>
{#if message?.text}
<div class="mb-3">{message.text}</div>
{/if}
<div id={`${scrollbarId}`}>
<div id={`chart-${message?.message_id}`} style="min-width: 1000px; max-height: 500px;"></div>
</div>
</div>
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
<script>
import Markdown from "$lib/common/markdown/Markdown.svelte";
import { RichType } from "$lib/helpers/enums";
import RcJsInterpreter from "./rc-js-interpreter.svelte";

/** @type {any} */
/** @type {import('$conversationTypes').ChatResponseModel?} */
export let message;

/** @type {string} */
Expand All @@ -12,13 +14,21 @@

/** @type {string} */
export let markdownClasses = '';

$: text = message?.rich_content?.message?.text || message?.text || '';
</script>

<div
class={`ctext-wrap bg-primary ${containerClasses}`}
style={`${containerStyles}`}
>
<div class="flex-shrink-0 align-self-center">
<Markdown containerClasses={markdownClasses} text={message?.rich_content?.message?.text || message?.text} rawText />
{#if text}
<div
class={`ctext-wrap bg-primary ${containerClasses}`}
style={`${containerStyles}`}
>
<div class="flex-shrink-0 align-self-center">
{#if message?.rich_content?.message?.rich_type === RichType.JsCode}
<RcJsInterpreter message={message} scrollable />
{:else}
<Markdown containerClasses={markdownClasses} text={text} rawText />
{/if}
</div>
</div>
</div>
{/if}
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,11 @@
}
</script>



{#if message?.rich_content?.editor === EditorType.File}
<ChatAttachmentOptions options={options} disabled={disabled} onConfirm={(title, payload) => handleConfirm(title, payload)} />
{/if}

{#if message?.rich_content?.editor !== EditorType.File}
{:else}
{#if !isComplexElement}
<RcPlainOptions options={options} isMultiSelect={isMultiSelect} disabled={disabled} onConfirm={(title, payload) => handleConfirm(title, payload)} />
{:else}
Expand Down