Files
developer-roadmap/src/lib/markdown.ts
T
Arik ChakmaandKamran Ahmed 62f31a4964 feat: roadmap chat (#8666)
* wip: roadmap chat

* wip

* wip

* wip

* wip

* wip: message rendering

* wip: roadmap topics rendering

* Update UI for premium page

* Update UI for premium page

* wip: topic resources rendering

* Update premium page design

* Update navigation design

* Update design for play iconsg

* Update design for play iconsg

* wip: resource progress

* Update premium page

* Refactor premium page

* wip: resource progress

* feat: enhance the progress rendering

* feat: add abort functionality to chat and update UI elements

* feat: add roadmap recommendations feature and new query for built-in roadmaps

* Grid -> flex

* Update chat

* Handle error screen

* wip

* fix: empty content check

* feat: show loading status

* feat: ai chat limit

* Refactor content parsing

* Handle the wrapping of tag in codeblocks

* Refactor

* Refactor chat

* Fix hydration error

* feat: topic details

* style: adjust padding and icon size in RoadmapAIChat component

* feat: add tab navigation for chat and topic details

* fix: chat and details scrolling issue

* fix: invalidate progress query

* Fix upgrade modal and issue with close button

* Refactor topic detail AI

* Update progress UI

* Shorten the text

* Rewrite frontend roadmap content

* Minor update to content

* Update shrinking issue

* Changes to ai chat

* UI changes for chat card

* UI changes for chat card

* Refactor progress actions list

* Update progress marking UI

* UI Changes

* Responsiveness of sidebar

* Responsiveness of sidebar

* Mobile window for roadmap chat

* Responsiveness of AI chat

* Close button fix

* Make roadmap ai chat header responsive

* Escape key handling to close

* Update topic rendering node

* Make default active tab to AI in topic popup

* User progress component

* Clear chat only visible when there is chat

* wip: user persona

* fix: hide upgrade button

* fix: show chat input for guest users

* feat: persona update

* Roadmap recommendations

* Update persona form

* Update tell us more

* Fix persona form

* Fix scroll issue

* Lock body scroll when mobile is active

* Add intro message

* Refactor and update

* Update UI for AI chat

---------

Co-authored-by: Kamran Ahmed <kamranahmed.se@gmail.com>
2025-05-27 21:02:36 +01:00

94 lines
2.4 KiB
TypeScript

// @ts-ignore
import MarkdownIt from 'markdown-it';
import MarkdownItAsync from 'markdown-it-async';
// replaces @variableName@ with the value of the variable
export function replaceVariables(
markdown: string,
variables: Record<string, string> = {},
): string {
const allVariables: Record<string, string> = {
...variables,
currentYear: new Date().getFullYear().toString(),
};
return markdown?.replace(/@([^@]+)@/g, (match, p1) => {
return allVariables[p1] || match;
});
}
const md = new MarkdownIt({
html: true,
linkify: true,
});
export function markdownToHtml(markdown: string, isInline = true): string {
try {
if (isInline) {
return md.renderInline(markdown);
} else {
return md.render(markdown);
}
} catch (e) {
return markdown;
}
}
// This is a workaround for the issue with tiptap-markdown extension
// It doesn't support links with escaped brackets like this:
// \\[link\\](https://example.com) -> [link](https://example.com)
export function sanitizeMarkdown(markdown: string) {
return markdown.replace(/\\\[([^\\]+)\\\]\(([^\\]+)\)/g, '[$1]($2)');
}
const markdownItAsync = MarkdownItAsync({
html: true,
linkify: true,
async highlight(code, lang, attrs) {
const { codeToHtml } = await import('shiki');
const html = await codeToHtml(code, {
lang: lang?.toLowerCase(),
theme: 'dracula',
}).catch((e) => {
console.warn(e);
return code;
});
return html;
},
});
export async function markdownToHtmlWithHighlighting(markdown: string) {
try {
// Solution to open links in new tab in markdown
// otherwise default behaviour is to open in same tab
//
// SOURCE: https://github.com/markdown-it/markdown-it/blob/master/docs/architecture.md#renderer
const defaultRender =
markdownItAsync.renderer.rules.link_open ||
function (tokens, idx, options, env, self) {
return self.renderToken(tokens, idx, options);
};
markdownItAsync.renderer.rules.link_open = function (
tokens,
idx,
options,
env,
self,
) {
// Add a new `target` attribute, or replace the value of the existing one.
tokens[idx].attrSet('target', '_blank');
// Pass the token to the default renderer.
return defaultRender(tokens, idx, options, env, self);
};
return markdownItAsync.renderAsync(markdown);
} catch (e) {
return markdown;
}
}