From f0abf195b8291cb8eae4ef0f511a5deb38503769 Mon Sep 17 00:00:00 2001 From: BearToCode Date: Wed, 3 Apr 2024 23:32:50 +0200 Subject: [PATCH 01/41] refactor: remove verbose prefixes Remove "Carta" prefixes from various interface/components. BREAKING CHANGE: Different objects have been renamed --- README.md | 4 +- docs/src/lib/examples/DiscordExample.svelte | 5 +- docs/src/lib/examples/GitHubExample.svelte | 4 +- .../examples/MathStackExchangeExample.svelte | 6 +- docs/src/pages/api/core.svelte.md | 12 ++-- docs/src/pages/api/extension.svelte.md | 34 +++++----- docs/src/pages/getting-started.svelte.md | 10 +-- docs/src/pages/plugins/anchor.svelte.md | 4 +- docs/src/pages/plugins/attachment.svelte.md | 4 +- docs/src/pages/plugins/code.svelte.md | 4 +- docs/src/pages/plugins/emoji.svelte.md | 4 +- docs/src/pages/plugins/math.svelte.md | 10 +-- docs/src/pages/plugins/slash.svelte.md | 4 +- docs/src/pages/plugins/tikz.svelte.md | 4 +- packages/carta-md/README.md | 4 +- .../{CartaViewer.svelte => Markdown.svelte} | 2 +- ...rtaEditor.svelte => MarkdownEditor.svelte} | 20 +++--- packages/carta-md/src/lib/index.ts | 12 ++-- packages/carta-md/src/lib/internal/carta.ts | 65 +++++++++---------- .../{MarkdownInput.svelte => Input.svelte} | 0 .../{CartaRenderer.svelte => Renderer.svelte} | 0 .../lib/internal/components/Toolbar.svelte | 4 +- .../carta-md/src/lib/internal/highlight.ts | 4 +- packages/carta-md/src/lib/internal/history.ts | 10 +-- packages/carta-md/src/lib/internal/icons.ts | 10 +-- packages/carta-md/src/lib/internal/input.ts | 14 ++-- packages/carta-md/src/lib/internal/labels.ts | 4 +- .../carta-md/src/lib/internal/renderer.ts | 2 +- .../carta-md/src/lib/internal/shortcuts.ts | 4 +- packages/carta-md/src/lib/internal/utils.ts | 1 + packages/carta-md/src/routes/+page.svelte | 4 +- packages/plugin-anchor/README.md | 4 +- packages/plugin-anchor/src/lib/index.ts | 4 +- .../plugin-anchor/src/routes/+page.svelte | 4 +- packages/plugin-attachment/README.md | 4 +- packages/plugin-attachment/src/lib/index.ts | 4 +- .../plugin-attachment/src/routes/+page.svelte | 4 +- packages/plugin-code/README.md | 4 +- packages/plugin-code/src/index.ts | 4 +- packages/plugin-emoji/README.md | 4 +- packages/plugin-emoji/src/lib/index.ts | 6 +- packages/plugin-emoji/src/routes/+page.svelte | 4 +- packages/plugin-math/README.md | 4 +- packages/plugin-math/src/index.ts | 4 +- packages/plugin-slash/README.md | 4 +- packages/plugin-slash/src/lib/index.ts | 6 +- packages/plugin-slash/src/lib/snippets.ts | 6 +- packages/plugin-slash/src/routes/+page.svelte | 4 +- packages/plugin-tikz/README.md | 4 +- packages/plugin-tikz/src/index.ts | 6 +- tsconfig.json | 3 +- 51 files changed, 179 insertions(+), 177 deletions(-) rename packages/carta-md/src/lib/{CartaViewer.svelte => Markdown.svelte} (95%) rename packages/carta-md/src/lib/{CartaEditor.svelte => MarkdownEditor.svelte} (90%) rename packages/carta-md/src/lib/internal/components/{MarkdownInput.svelte => Input.svelte} (100%) rename packages/carta-md/src/lib/internal/components/{CartaRenderer.svelte => Renderer.svelte} (100%) diff --git a/README.md b/README.md index 4508e54..806997a 100644 --- a/README.md +++ b/README.md @@ -99,7 +99,7 @@ npm i @cartamd/plugin-name ```svelte - + diff --git a/packages/carta-md/src/routes/sample.md b/packages/carta-md/src/routes/sample.md new file mode 100644 index 0000000..3da9df0 --- /dev/null +++ b/packages/carta-md/src/routes/sample.md @@ -0,0 +1,79 @@ +# Heading + +## Sub-heading + +Paragraphs are separated +by a blank line. + +Two spaces at the end of a line +produce a line break. + +Text attributes _italic_, +**bold**, `monospace`. Some `console.log(lst.filter(e => e == true))` implementations may use _single-asterisks_ for italic text. + +Horizontal rule: + +--- + +```js +function resolveAfter2Seconds(x) { + return new Promise((resolve) => { + setTimeout(() => { + resolve(x); + }, 2000); + }); +} + +// async function expression assigned to a variable +const add = async function (x) { + const a = await resolveAfter2Seconds(20); + const b = await resolveAfter2Seconds(30); + console?.log(`http://localhost:${PORT}/`.match(/:[0-9]{2,4}^/g)); + return x + a + b; +}; + +add(10).then((v) => { + console.log(v); // prints 60 after 4 seconds. +}); + +// async function expression used as an IIFE +(async function (x) { + const p1 = resolveAfter2Seconds(20); + const p2 = resolveAfter2Seconds(30); + return x + (await p1) + (await p2); +})(10).then((v) => { + console.log(v); // prints 60 after 2 seconds. +}); +``` + +```beurihiuerh +} +``` + +Strikethrough: +~~strikethrough~~ + +Bullet list: + +- apples +- oranges +- pears + +Numbered list: + +1. lather +2. rinse +3. repeat + +An [example](http://example.com). + +![Image](Icon-pictures.png 'icon') + +> Markdown uses email-style +> characters for blockquoting. +> Multiple paragraphs need to be prepended individually. + +| Item | Price | # In stock | +| ------------ | -------- | ---------- | +| Juicy Apples | 1.99 | _7_ | +| Bananas | **1.89** | 5234 | diff --git a/packages/plugin-code/package.json b/packages/plugin-code/package.json index bdb372b..e2858c6 100644 --- a/packages/plugin-code/package.json +++ b/packages/plugin-code/package.json @@ -18,9 +18,10 @@ "devDependencies": { "@types/node": "^18.16.3", "carta-md": "workspace:*", + "marked": "^9.1.5", + "shiki": "^1.2.4", "typescript": "^5.0.4", - "typescript-cp": "^0.1.8", - "marked": "^9.1.5" + "typescript-cp": "^0.1.8" }, "peerDependencies": { "carta-md": "^3.0.0" diff --git a/packages/plugin-code/src/index.ts b/packages/plugin-code/src/index.ts index 605e5df..cc08311 100644 --- a/packages/plugin-code/src/index.ts +++ b/packages/plugin-code/src/index.ts @@ -1,21 +1,34 @@ -import type { Plugin, HighlightFunctions } from 'carta-md'; +import { type Carta, type DualTheme, type Plugin, type Theme } from 'carta-md'; +import type { BundledTheme, CodeOptionsSingleTheme } from 'shiki'; import { markedHighlight } from 'marked-highlight'; +type ShikiOptions = Omit, 'theme' | 'lang'>; interface CodeExtensionOptions { /** - * Default language when none is provided. + * Shiki options for the highlighter. The language is automatically set to the code block's language. + * If you want to load a custom theme/lang, remember to provide the corresponding file when loading + * carta! + * + * ```ts + * const carta = new Carta({ + * shikiOptions: { + * themes: [...], + * langs: [...] + * } + * }); + * ``` */ - defaultLanguage?: string; + shikiOptions?: ShikiOptions; /** - * Whether to autodetect a language when none is provided. - * Overwritten by `defaultLanguage`. + * Default language for code blocks. + * @default 'plaintext' */ - autoDetect?: string; + defaultLang?: string; /** - * Line numbering. - * @defaults false. + * Shiki theme to use for code highlighting. + * @default Theme specified for the editor */ - lineNumbering?: boolean; + theme: Theme | DualTheme; /** * Options for custom syntax highlighting. @@ -34,35 +47,60 @@ interface CodeExtensionOptions { }; } -let shj: HighlightFunctions; - /** * Carta code highlighting plugin. Themes available on [GitHub](https://github.com/speed-highlight/core/tree/main/dist/themes). */ export const code = (options?: CodeExtensionOptions): Plugin => { + let carta: Carta; return { - onLoad: ({ highlight }) => (shj = highlight), + onLoad: ({ carta: c }) => (carta = c), markedExtensions: [ markedHighlight({ - langPrefix: options?.customHighlight?.langPrefix ?? 'shj-lang-', + langPrefix: options?.customHighlight?.langPrefix, async: true, async highlight(code, lang) { if (options?.customHighlight) { return await options.customHighlight.highlighter(code, lang); } - const { highlight, highlightAutodetect } = shj; + const highlighter = await carta.highlighter(); - lang ||= options?.defaultLanguage ?? ''; - let highlighted: string | null = null; + const defaultLang = options?.defaultLang ?? 'plaintext'; + const theme = options?.theme ?? highlighter.theme; - if (lang) highlighted = await highlight(code, lang, !(options?.lineNumbering ?? false)); - if (highlighted) return highlighted; + lang = lang || defaultLang; - if (options?.autoDetect ?? true) - return await highlightAutodetect(code, !(options?.lineNumbering ?? false)); + // Load the theme if it's not already loaded + const loadTheme = async (theme: Theme) => { + const themeName = highlighter.isThemeRegistration(theme) ? theme.name ?? '' : theme; + if ( + !highlighter.getLoadedThemes().includes(themeName) && + highlighter.isBundleTheme(themeName) + ) { + await highlighter.loadTheme(themeName); + } + }; - return (await highlight(code, 'plain', !(options?.lineNumbering ?? false))) as string; + if (highlighter.isSingleTheme(theme)) { + await loadTheme(theme); + } else { + await loadTheme(theme.light); + await loadTheme(theme.dark); + } + + // Load the language if it's not already loaded + if ( + !highlighter.getLoadedLanguages().includes(lang) && + highlighter.isBundleLanguage(lang) + ) { + await highlighter.loadLanguage(lang); + } + + if (highlighter.isSingleTheme(theme)) { + return highlighter.codeToHtml(code, { lang, theme, ...options?.shikiOptions }); + } else { + return highlighter.codeToHtml(code, { lang, themes: theme, ...options?.shikiOptions }); + } } }) ] diff --git a/packages/plugin-emoji/src/lib/index.ts b/packages/plugin-emoji/src/lib/index.ts index 1d8a14d..c5ec8c9 100644 --- a/packages/plugin-emoji/src/lib/index.ts +++ b/packages/plugin-emoji/src/lib/index.ts @@ -1,4 +1,4 @@ -import type { Plugin, ExtensionComponent } from 'carta-md'; +import type { Plugin, ExtensionComponent, GrammarRule, HighlightingRule } from 'carta-md'; import type { TokenizerAndRendererExtension } from 'marked'; import { fade, scale, type TransitionConfig } from 'svelte/transition'; import nodeEmoji from 'node-emoji'; @@ -49,6 +49,30 @@ export const emoji = (options?: EmojiExtensionOptions): Plugin => { } }; + const grammar = { + name: 'emoji', + type: 'inline', + definition: { + match: ':[a-zA-Z_]+:', + name: 'markup.emoji.markdown' + } + } satisfies GrammarRule; + + const highlighting = { + light: { + scope: 'markup.emoji', + settings: { + foreground: '#3bf' + } + }, + dark: { + scope: 'markup.emoji', + settings: { + foreground: '#4dacfa' + } + } + } satisfies HighlightingRule; + return { markedExtensions: [ { @@ -56,12 +80,8 @@ export const emoji = (options?: EmojiExtensionOptions): Plugin => { } ], components: [emojiComponent], - highlightRules: [ - { - type: 'oper', - match: /:[a-z0-9_]+:/g - } - ] + grammarRules: [grammar], + highlightingRules: [highlighting] }; }; diff --git a/packages/plugin-emoji/src/routes/+page.svelte b/packages/plugin-emoji/src/routes/+page.svelte index 4f50c22..6be0a8d 100644 --- a/packages/plugin-emoji/src/routes/+page.svelte +++ b/packages/plugin-emoji/src/routes/+page.svelte @@ -32,9 +32,10 @@ min-height: 100vh; } - :global(.carta-font-code, code) { + :global(.carta-font-code) { font-family: 'Fira Code', monospace; font-variant-ligatures: normal; + font-size: 1.1rem; } :global(input, textarea, button) { diff --git a/packages/plugin-math/src/index.ts b/packages/plugin-math/src/index.ts index 6bde010..9f473fa 100644 --- a/packages/plugin-math/src/index.ts +++ b/packages/plugin-math/src/index.ts @@ -1,4 +1,4 @@ -import type { Carta, Plugin } from 'carta-md'; +import type { Plugin } from 'carta-md'; import { TokenizerAndRendererExtension } from 'marked'; import katex, { KatexOptions } from 'katex'; @@ -49,18 +49,14 @@ function safeRender(tex: string, options?: KatexOptions | undefined) { } } -let carta: Carta; - /** * Carta math plugin. Code adapted from [marked-katex-extension](https://github.com/UziTech/marked-katex-extension). */ export const math = (options?: MathExtensionOptions): Plugin => { return { - onLoad: ({ carta: c, highlight: shj }) => { - carta = c; - import('./latex.js') - .then((module) => shj.loadCustomLanguage('latex', module)) - .then(() => carta.input?.update()); + onLoad: async ({ carta }) => { + const highlighter = await carta.highlighter(); + await highlighter.loadLanguage('latex'); }, markedExtensions: [ { @@ -79,14 +75,56 @@ export const math = (options?: MathExtensionOptions): Plugin => { action: (input) => input.toggleSelectionSurrounding(['$$\n', '\n$$']) } ], - highlightRules: [ + grammarRules: [ { - match: /\$[{}[\]a-zA-Z0-9.+-_=*/\\ ]+\$/g, - sub: 'latex' + name: 'inline_math', + type: 'inline', + definition: { + match: '(\\$+)((?:[^\\$]|(?!(? void; } -let carta: Carta; - /** * TikzJax extension for Carta. * @param options Tikz options. */ export const tikz = (options?: TikzExtensionOptions): Plugin => { + let carta: Carta; return { - cartaRef: (c) => (carta = c), - shjRef: (shj) => { - import('./tikz') - .then((module) => shj.loadCustomLanguage('tikz', module)) - .then(() => carta.input?.update()); + onLoad: async ({ carta: c }) => { + carta = c; + + const highlighter = await carta.highlighter(); + await highlighter.loadLanguage('latex'); }, markedExtensions: [ { async: true, - extensions: [tikzTokenizer(options)] + extensions: [tikzTokenizer(() => carta, options)] } ], - listeners: [['carta-render', (e) => generateTikzImages(e, options)]] + listeners: [['carta-render', (e) => generateTikzImages(e, options)]], + grammarRules: [ + { + name: 'tikz', + type: 'block', + definition: { + begin: '(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(tikz)((\\s+|:|,|\\{|\\?)[^`]*)?$)', + beginCaptures: { + '3': { name: 'punctuation.definition.markdown' }, + '4': { name: 'fenced_code.block.language.markdown' }, + '5': { name: 'fenced_code.block.language.attributes.markdown' } + }, + end: '(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$', + endCaptures: { '3': { name: 'punctuation.definition.markdown' } }, + name: 'markup.fenced_code.block.markdown', + patterns: [ + { + begin: '(^|\\G)(\\s*)(.*)', + contentName: 'meta.embedded.block.latex', + patterns: [{ include: 'text.tex.latex' }], + while: '(^|\\G)(?!\\s*([`~]{3,})\\s*$)' + } + ] + } + } + ] }; }; // Keeps track of tikz generation to remove previous items let currentGeneration = 0; -const tikzTokenizer = (options?: TikzExtensionOptions): TokenizerAndRendererExtension => { +const tikzTokenizer = ( + cartaRef: () => Carta, + options?: TikzExtensionOptions +): TokenizerAndRendererExtension => { return { name: 'tikz', level: 'block', @@ -101,7 +128,7 @@ const tikzTokenizer = (options?: TikzExtensionOptions): TokenizerAndRendererExte html = template.outerHTML; } - const sanitizer = carta.options?.sanitizer; + const sanitizer = cartaRef().options?.sanitizer; if (sanitizer) html = sanitizer(html); return ` diff --git a/packages/plugin-tikz/src/tikz.ts b/packages/plugin-tikz/src/tikz.ts deleted file mode 100644 index 7050195..0000000 --- a/packages/plugin-tikz/src/tikz.ts +++ /dev/null @@ -1,26 +0,0 @@ -export default [ - { - match: /\\(usepackage|input|usemodule)(?![a-zA-Z0-9])/g, - type: 'str' - }, - { - match: /\\(begin|end|node)(?![a-zA-Z0-9])/g, - type: 'class' - }, - { - match: /\\[a-zA-Z0-9]+/g, - type: 'oper' - }, - { - match: /%.+$/gm, - type: 'cmnt' - }, - { - match: /(\(|\)|\{|\}|\[|\])/g, - type: 'esc' - }, - { - match: /[0-9]+[a-z]{0,3}/g, - type: 'num' - } -]; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f890f2b..443c019 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -159,12 +159,12 @@ importers: packages/carta-md: dependencies: - '@speed-highlight/core': - specifier: 1.2.2 - version: 1.2.2 marked: specifier: ^9.1.5 version: 9.1.5 + shiki: + specifier: ^1.2.4 + version: 1.2.4 svelte: specifier: ^3.54.0 || ^4.0.0 version: 4.2.2 @@ -294,6 +294,9 @@ importers: marked: specifier: ^9.1.5 version: 9.1.5 + shiki: + specifier: ^1.2.4 + version: 1.2.4 typescript: specifier: ^5.0.4 version: 5.0.4 @@ -1393,9 +1396,8 @@ packages: - supports-color dev: true - /@speed-highlight/core@1.2.2: - resolution: {integrity: sha512-Yb3ewAUq7QwLbU+vF28dxkOmBJG5bHUVWZWQBnUt2GIhVWdiShKcE6kBMsCRXvD8AuK7gy0rR4qNckqZnCzEFw==} - dev: false + /@shikijs/core@1.2.4: + resolution: {integrity: sha512-ClaUWpt8oTzjcF0MM1P81AeWyzc1sNSJlAjMG80CbwqbFqXSNz+NpQVUC0icobt3sZn43Sn27M4pHD/Jmp3zHw==} /@sveltejs/adapter-auto@3.1.1(@sveltejs/kit@2.5.4): resolution: {integrity: sha512-6LeZft2Fo/4HfmLBi5CucMYmgRxgcETweQl/yQoZo/895K3S9YWYN4Sfm/IhwlIpbJp3QNvhKmwCHbsqQNYQpw==} @@ -5734,6 +5736,11 @@ packages: engines: {node: '>=8'} dev: true + /shiki@1.2.4: + resolution: {integrity: sha512-Q9n9jKiOjJCRPztA9POn3/uZXNySHDNKAsPNpmtHDcFyi6ZQhx5vQKZW3Nhrwn8TWW3RudSRk66zqY603EZDeg==} + dependencies: + '@shikijs/core': 1.2.4 + /signal-exit@3.0.7: resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} dev: true From ae15b5b590a56bba0761b9f0612ee619574e9a24 Mon Sep 17 00:00:00 2001 From: BearToCode Date: Sun, 7 Apr 2024 22:25:07 +0200 Subject: [PATCH 03/41] feat: use shiki for syntax highlighting Remove Speed-Syntax Highlight, as the newer versions stopped working, and use ShikiJS instead. Also has better syntax and more languages supported. BREAKING CHANGE: Replace SHJ with ShikiJS, removed old themes and added new ones. --- packages/carta-md/src/lib/internal/carta.ts | 4 ++-- .../carta-md/src/lib/internal/components/Input.svelte | 9 ++++++--- packages/plugin-math/src/index.ts | 1 + packages/plugin-tikz/src/index.ts | 1 + 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/packages/carta-md/src/lib/internal/carta.ts b/packages/carta-md/src/lib/internal/carta.ts index 89e316e..b32efbb 100644 --- a/packages/carta-md/src/lib/internal/carta.ts +++ b/packages/carta-md/src/lib/internal/carta.ts @@ -193,8 +193,8 @@ export class Carta { shiki: this.options?.shikiOptions }); }; - this.mHighlighter = promise(); // Cache the promise, so that it doesn't get called multiple times - this.mHighlighter = await this.mHighlighter; // Await the promise // FIXME: This is a hack to make TypeScript happy + this.mHighlighter = promise(); + this.mHighlighter = await this.mHighlighter; } return this.mHighlighter; } diff --git a/packages/carta-md/src/lib/internal/components/Input.svelte b/packages/carta-md/src/lib/internal/components/Input.svelte index 4c5b3b2..3f36c69 100644 --- a/packages/carta-md/src/lib/internal/components/Input.svelte +++ b/packages/carta-md/src/lib/internal/components/Input.svelte @@ -64,7 +64,6 @@ const findNestedLanguages = (text: string) => { const languages = new Set(); - text = text.replaceAll('\r\n', '\n'); const regex = /```([a-z]+)\n([\s\S]+?)\n```/g; let match: RegExpExecArray | null; @@ -91,8 +90,12 @@ } }, 500); - $: highlight(value).then(resize); - $: loadNestedLanguages(value); + const normalize = (text: string) => { + return text.replaceAll('\r\n', '\n'); + }; + + $: highlight(normalize(value)).then(resize); + $: loadNestedLanguages(normalize(value)); onMount(() => { mounted = true; diff --git a/packages/plugin-math/src/index.ts b/packages/plugin-math/src/index.ts index 9f473fa..c86fe22 100644 --- a/packages/plugin-math/src/index.ts +++ b/packages/plugin-math/src/index.ts @@ -57,6 +57,7 @@ export const math = (options?: MathExtensionOptions): Plugin => { onLoad: async ({ carta }) => { const highlighter = await carta.highlighter(); await highlighter.loadLanguage('latex'); + carta.input?.update(); }, markedExtensions: [ { diff --git a/packages/plugin-tikz/src/index.ts b/packages/plugin-tikz/src/index.ts index e08eb3d..4067683 100644 --- a/packages/plugin-tikz/src/index.ts +++ b/packages/plugin-tikz/src/index.ts @@ -42,6 +42,7 @@ export const tikz = (options?: TikzExtensionOptions): Plugin => { const highlighter = await carta.highlighter(); await highlighter.loadLanguage('latex'); + carta.input?.update(); }, markedExtensions: [ { From eb647b416f87c35a49ea997f0824ae8615c68c6e Mon Sep 17 00:00:00 2001 From: BearToCode Date: Sun, 7 Apr 2024 22:44:19 +0200 Subject: [PATCH 04/41] refactor: do not store options inside `Carta` BREAKING CHANGE: Remove `Carta.options`. Update API --- packages/carta-md/src/lib/internal/carta.ts | 32 ++++++++++++------- .../src/lib/internal/components/Input.svelte | 4 +-- .../lib/internal/components/Renderer.svelte | 2 +- packages/carta-md/src/lib/internal/history.ts | 8 ++--- packages/plugin-tikz/src/index.ts | 2 +- 5 files changed, 29 insertions(+), 19 deletions(-) diff --git a/packages/carta-md/src/lib/internal/carta.ts b/packages/carta-md/src/lib/internal/carta.ts index b32efbb..14c3ad6 100644 --- a/packages/carta-md/src/lib/internal/carta.ts +++ b/packages/carta-md/src/lib/internal/carta.ts @@ -95,7 +95,7 @@ export interface Options { /** * History (Undo/Redo) options. */ - historyOptions?: Partial; + historyOptions?: TextAreaHistoryOptions; /** * HTML sanitizer. */ @@ -158,6 +158,11 @@ export interface Plugin { } export class Carta { + public readonly sanitizer?: (html: string) => string; + public readonly historyOptions?: TextAreaHistoryOptions; + public readonly theme?: Theme | DualTheme; + public readonly shikiOptions?: ShikiOptions; + public readonly rendererDebounce: number; public readonly keyboardShortcuts: KeyboardShortcut[]; public readonly icons: Icon[]; public readonly prefixes: Prefix[]; @@ -187,10 +192,10 @@ export class Carta { if (!this.mHighlighter) { const promise = async () => { return loadHighlighter({ - theme: this.options?.theme ?? (await loadDefaultTheme()), + theme: this.theme ?? (await loadDefaultTheme()), grammarRules: this.grammarRules, highlightingRules: this.highlightingRules, - shiki: this.options?.shikiOptions + shiki: this.shikiOptions }); }; this.mHighlighter = promise(); @@ -205,8 +210,14 @@ export class Carta { callback: (() => void) | undefined; }[] = []; - public constructor(public readonly options?: Options) { - // TODO: do not store options + public constructor(options?: Options) { + this.sanitizer = options?.sanitizer; + this.historyOptions = options?.historyOptions; + this.theme = options?.theme; + this.shikiOptions = options?.shikiOptions; + this.rendererDebounce = options?.rendererDebounce ?? 300; + + // Load plugins this.keyboardShortcuts = []; this.icons = []; this.prefixes = []; @@ -217,7 +228,6 @@ export class Carta { this.highlightingRules = []; const listeners = []; - for (const ext of options?.extensions ?? []) { this.keyboardShortcuts.push(...(ext.shortcuts ?? [])); this.icons.push(...(ext.icons ?? [])); @@ -262,7 +272,7 @@ export class Carta { ); // Load marked extensions - const markedExtensions = this.options?.extensions + const markedExtensions = options?.extensions ?.flatMap((ext) => ext.markedExtensions) .filter((ext) => ext != null) as MarkedExtension[] | undefined; if (markedExtensions) @@ -270,7 +280,7 @@ export class Carta { this.useMarkedExtension(ext); }); - for (const ext of this.options?.extensions ?? []) { + for (const ext of options?.extensions ?? []) { ext.onLoad && ext.onLoad({ carta: this @@ -294,7 +304,7 @@ export class Carta { this.dispatcher.dispatchEvent( new CustomEvent<{ carta: Carta }>('carta-render', { detail: { carta: this } }) ); - return (this.options?.sanitizer && this.options?.sanitizer(dirty)) ?? dirty; + return (this.sanitizer && this.sanitizer(dirty)) ?? dirty; } /** @@ -308,7 +318,7 @@ export class Carta { this.dispatcher.dispatchEvent( new CustomEvent<{ carta: Carta }>('carta-render-ssr', { detail: { carta: this } }) ); - if (this.options?.sanitizer) return this.options.sanitizer(dirty); + if (this.sanitizer) return this.sanitizer(dirty); return dirty; } @@ -333,7 +343,7 @@ export class Carta { shortcuts: this.keyboardShortcuts, prefixes: this.prefixes, listeners: this.textareaListeners, - historyOpts: this.options?.historyOptions + historyOpts: this.historyOptions }); if (previousInput) { diff --git a/packages/carta-md/src/lib/internal/components/Input.svelte b/packages/carta-md/src/lib/internal/components/Input.svelte index 3f36c69..728c1ef 100644 --- a/packages/carta-md/src/lib/internal/components/Input.svelte +++ b/packages/carta-md/src/lib/internal/components/Input.svelte @@ -55,8 +55,8 @@ }); } - if (carta.options?.sanitizer) { - highlighted = carta.options.sanitizer(html); + if (carta.sanitizer) { + highlighted = carta.sanitizer(html); } else { highlighted = html; } diff --git a/packages/carta-md/src/lib/internal/components/Renderer.svelte b/packages/carta-md/src/lib/internal/components/Renderer.svelte index 472a4d3..1141749 100644 --- a/packages/carta-md/src/lib/internal/components/Renderer.svelte +++ b/packages/carta-md/src/lib/internal/components/Renderer.svelte @@ -13,7 +13,7 @@ const debouncedRenderer = debounce(() => { carta.render(value).then((rendered) => (renderedHtml = rendered)); - }, carta.options?.rendererDebounce ?? 300); + }, carta.rendererDebounce ?? 300); $: { // On value updates diff --git a/packages/carta-md/src/lib/internal/history.ts b/packages/carta-md/src/lib/internal/history.ts index 43aa5a5..450c1a7 100644 --- a/packages/carta-md/src/lib/internal/history.ts +++ b/packages/carta-md/src/lib/internal/history.ts @@ -11,12 +11,12 @@ export interface TextAreaHistoryOptions { * Minimum interval between save states in ms. * @default 300ms */ - minInterval: number; + minInterval?: number; /** * Maximum history size in bytes. * @default 1MB */ - maxSize: number; + maxSize?: number; } const defaultHistoryOptions: TextAreaHistoryOptions = { @@ -79,7 +79,7 @@ export class TextAreaHistory { } this.currentIndex = -1; - if (latest && Date.now() - latest.timestamp.getTime() <= this.options.minInterval) { + if (latest && Date.now() - latest.timestamp.getTime() <= (this.options.minInterval ?? 300)) { this.states.pop(); } @@ -94,7 +94,7 @@ export class TextAreaHistory { // every char is 2 bytes size += value.length * 2; - while (size > this.options.maxSize) { + while (size > (this.options.maxSize ?? 1_000_000)) { const removed = this.states.shift(); if (!removed) break; // This should never happen size -= removed.value.length * 2; diff --git a/packages/plugin-tikz/src/index.ts b/packages/plugin-tikz/src/index.ts index 4067683..2c92711 100644 --- a/packages/plugin-tikz/src/index.ts +++ b/packages/plugin-tikz/src/index.ts @@ -129,7 +129,7 @@ const tikzTokenizer = ( html = template.outerHTML; } - const sanitizer = cartaRef().options?.sanitizer; + const sanitizer = cartaRef().sanitizer; if (sanitizer) html = sanitizer(html); return ` From 24be57a10fb07b09175723029841eb276ac7219e Mon Sep 17 00:00:00 2001 From: BearToCode Date: Mon, 8 Apr 2024 22:15:06 +0200 Subject: [PATCH 05/41] refactor: require explicit disabling of sanitizer BREAKING CHANGE: Require `sanitizer` to be provided in the options. To disable it, set it explicitly to `false`. --- packages/carta-md/src/lib/internal/carta.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/carta-md/src/lib/internal/carta.ts b/packages/carta-md/src/lib/internal/carta.ts index 14c3ad6..9a3175b 100644 --- a/packages/carta-md/src/lib/internal/carta.ts +++ b/packages/carta-md/src/lib/internal/carta.ts @@ -99,7 +99,7 @@ export interface Options { /** * HTML sanitizer. */ - sanitizer?: (html: string) => string; + sanitizer: ((html: string) => string) | false; /** * Highlighter options. */ @@ -211,7 +211,7 @@ export class Carta { }[] = []; public constructor(options?: Options) { - this.sanitizer = options?.sanitizer; + this.sanitizer = options?.sanitizer || undefined; this.historyOptions = options?.historyOptions; this.theme = options?.theme; this.shikiOptions = options?.shikiOptions; From d1590ea384d28d3637bcb2f8ed51e56a864f95ab Mon Sep 17 00:00:00 2001 From: BearToCode Date: Mon, 8 Apr 2024 22:27:14 +0200 Subject: [PATCH 06/41] build: move plugins peer-deps to v4 --- packages/plugin-anchor/package.json | 2 +- packages/plugin-attachment/package.json | 2 +- packages/plugin-code/package.json | 2 +- packages/plugin-emoji/package.json | 2 +- packages/plugin-math/package.json | 2 +- packages/plugin-slash/package.json | 2 +- packages/plugin-tikz/package.json | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/plugin-anchor/package.json b/packages/plugin-anchor/package.json index ee4ce78..aca9b88 100644 --- a/packages/plugin-anchor/package.json +++ b/packages/plugin-anchor/package.json @@ -35,7 +35,7 @@ "slugify": "^1.6.6" }, "peerDependencies": { - "carta-md": "^3.1.0", + "carta-md": "^4.0.0", "marked": "^9.1.5", "svelte": "^3.54.0 || ^4.0.0" }, diff --git a/packages/plugin-attachment/package.json b/packages/plugin-attachment/package.json index 8710bdc..8f68e67 100644 --- a/packages/plugin-attachment/package.json +++ b/packages/plugin-attachment/package.json @@ -34,7 +34,7 @@ "!dist/**/*.spec.*" ], "peerDependencies": { - "carta-md": "^3.4.0", + "carta-md": "^4.0.0", "marked": "^9.1.5", "svelte": "^3.54.0 || ^4.0.0" }, diff --git a/packages/plugin-code/package.json b/packages/plugin-code/package.json index e2858c6..7143db1 100644 --- a/packages/plugin-code/package.json +++ b/packages/plugin-code/package.json @@ -24,7 +24,7 @@ "typescript-cp": "^0.1.8" }, "peerDependencies": { - "carta-md": "^3.0.0" + "carta-md": "^4.0.0" }, "files": [ "dist" diff --git a/packages/plugin-emoji/package.json b/packages/plugin-emoji/package.json index a895776..bc8c9ab 100644 --- a/packages/plugin-emoji/package.json +++ b/packages/plugin-emoji/package.json @@ -36,7 +36,7 @@ "node-emoji": "^1.11.0" }, "peerDependencies": { - "carta-md": "^3.1.0", + "carta-md": "^4.0.0", "marked": "^9.1.5", "svelte": "^3.54.0 || ^4.0.0" }, diff --git a/packages/plugin-math/package.json b/packages/plugin-math/package.json index fba345e..e94a942 100644 --- a/packages/plugin-math/package.json +++ b/packages/plugin-math/package.json @@ -23,7 +23,7 @@ "typescript": "^5.0.4" }, "peerDependencies": { - "carta-md": "^3.0.0", + "carta-md": "^4.0.0", "katex": "^0.16.10", "marked": "^9.1.5" }, diff --git a/packages/plugin-slash/package.json b/packages/plugin-slash/package.json index ee384b6..3b70ace 100644 --- a/packages/plugin-slash/package.json +++ b/packages/plugin-slash/package.json @@ -35,7 +35,7 @@ "bezier-easing": "^2.1.0" }, "peerDependencies": { - "carta-md": "^3.1.0", + "carta-md": "^4.0.0", "svelte": "^3.54.0 || ^4.0.0" }, "devDependencies": { diff --git a/packages/plugin-tikz/package.json b/packages/plugin-tikz/package.json index ec4f9f5..c38c458 100644 --- a/packages/plugin-tikz/package.json +++ b/packages/plugin-tikz/package.json @@ -28,7 +28,7 @@ "vite-raw-plugin": "^1.0.2" }, "peerDependencies": { - "carta-md": "^3.0.0", + "carta-md": "^4.0.0", "marked": "^9.1.5" }, "files": [ From c6a81acedd7112e3c8638e1491e9878c3637e6ee Mon Sep 17 00:00:00 2001 From: BearToCode Date: Mon, 8 Apr 2024 22:32:19 +0200 Subject: [PATCH 07/41] fix: default theme caret color --- packages/carta-md/src/lib/default.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/carta-md/src/lib/default.css b/packages/carta-md/src/lib/default.css index 5f1df92..747e5c0 100644 --- a/packages/carta-md/src/lib/default.css +++ b/packages/carta-md/src/lib/default.css @@ -3,7 +3,7 @@ --selection-color: #b5f0ff3d; --focus-outline: #76bbf3; --hover-color: #e9e9e9; - --caret-color: #4d4d4c; + --caret-color: #161616; --text-color: #1a1a1a; --border-color-dark: #4d4d4c; @@ -38,7 +38,7 @@ /* Text settings */ .carta-theme__default .carta-input { - caret-color: #4d4d4c; + caret-color: var(--caret-color); font-size: 0.95rem; } From b30b2af6d96dd2c78000d360af585e986baf6e38 Mon Sep 17 00:00:00 2001 From: BearToCode Date: Tue, 9 Apr 2024 20:58:05 +0200 Subject: [PATCH 08/41] fix: default theme placeholder color --- packages/carta-md/src/lib/default.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/carta-md/src/lib/default.css b/packages/carta-md/src/lib/default.css index 747e5c0..27de0bd 100644 --- a/packages/carta-md/src/lib/default.css +++ b/packages/carta-md/src/lib/default.css @@ -42,6 +42,10 @@ font-size: 0.95rem; } +.carta-theme__default .carta-input ::placeholder { + color: var(--text-color); +} + /* Splitter */ .carta-theme__default .mode-split.carta-container::after { content: ''; From 9e1b0d1850a3969e69f41f472372d86d4b02db87 Mon Sep 17 00:00:00 2001 From: BearToCode Date: Tue, 9 Apr 2024 21:00:08 +0200 Subject: [PATCH 09/41] docs: update README --- README.md | 44 +++++++++++++++++-------------------- packages/carta-md/README.md | 34 ++++++++++++++-------------- 2 files changed, 36 insertions(+), 42 deletions(-) diff --git a/README.md b/README.md index 806997a..5832d66 100644 --- a/README.md +++ b/README.md @@ -1,28 +1,24 @@ - +[![Carta.png](https://i.postimg.cc/nV6DMXKM/Carta.png)](https://beartocode.github.io/carta/)
-
Carta
-
Swiftly edit and render Markdown, with no overhead.
+

Carta

+
Modern, lightweight, powerful Markdown Editor.

Documentation @@ -39,19 +35,19 @@ Differently from most editors, Carta includes neither ProseMirror nor CodeMirror ## Features -- Keyboard **shortcuts** (extensible); -- Toolbar (extensible); -- Markdown syntax highlighting; -- Scroll sync; -- Accessibility friendly; -- **SSR** compatible; -- **Katex** support (plugin); -- **Slash** commands (plugin); -- **Emojis**, with included search (plugin); -- **Tikz** support (plugin); -- **Attachment** support (plugin); -- **Anchor** links in headings; -- Code blocks **syntax highlighting** (plugin). +- ⌨️ Keyboard **shortcuts** (extensible); +- 🛠️ Toolbar (extensible); +- 🌈 Markdown syntax highlighting; +- 🔀 Scroll sync; +- ✅ Accessibility friendly; +- 💻 **SSR** compatible; +- ⚗️ **KaTeX** support (plugin); +- 🔨 **Slash** commands (plugin); +- 😄 **Emojis**, with included search (plugin); +- ✏️ **TikZ** support (plugin); +- 📂 **Attachment** support (plugin); +- ⚓ **Anchor** links in headings; +- 🌈 Code blocks **syntax highlighting** (plugin). ## Packages diff --git a/packages/carta-md/README.md b/packages/carta-md/README.md index 2b5ad6f..6f32c52 100644 --- a/packages/carta-md/README.md +++ b/packages/carta-md/README.md @@ -13,16 +13,12 @@
- +[![Carta.png](https://i.postimg.cc/nV6DMXKM/Carta.png)](https://beartocode.github.io/carta/)
-
Carta
-
Swiftly edit and render Markdown, with no overhead.
+

Carta

+
Modern, lightweight, powerful Markdown Editor.

Documentation @@ -39,17 +35,19 @@ Differently from most editors, Carta includes neither ProseMirror nor CodeMirror ## Features -- Keyboard **shortcuts** (extensible); -- Toolbar (extensible); -- Markdown syntax highlighting; -- Scroll sync; -- **SSR** compatible; -- **Katex** support (plugin); -- **Slash** commands (plugin); -- **Emojis**, with included search (plugin); -- **Tikz** support(plugin); -- **Attachment** support(plugin); -- Code blocks **syntax highlighting** (plugin). +- ⌨️ Keyboard **shortcuts** (extensible); +- 🛠️ Toolbar (extensible); +- 🌈 Markdown syntax highlighting; +- 🔀 Scroll sync; +- ✅ Accessibility friendly; +- 💻 **SSR** compatible; +- ⚗️ **KaTeX** support (plugin); +- 🔨 **Slash** commands (plugin); +- 😄 **Emojis**, with included search (plugin); +- ✏️ **TikZ** support (plugin); +- 📂 **Attachment** support (plugin); +- ⚓ **Anchor** links in headings; +- 🌈 Code blocks **syntax highlighting** (plugin). # Getting started From 342c8d24d0172aa2bec8609965e587613025904a Mon Sep 17 00:00:00 2001 From: BearToCode Date: Thu, 11 Apr 2024 17:52:09 +0200 Subject: [PATCH 10/41] feat: use unified+rehype for parsing markdown `marked` has been replaced with a more modern setup involving Unified JS, Rehype and various plugins. BREAKING CHANGE: Replaced `marked` with `unified` and `rehype` --- .vscode/settings.json | 2 + README.md | 2 - docs/src/lib/examples/DiscordExample.svelte | 1 + docs/src/lib/examples/GitHubExample.svelte | 1 + .../examples/MathStackExchangeExample.svelte | 1 + packages/carta-md/README.md | 2 - packages/carta-md/package.json | 8 +- packages/carta-md/src/lib/Markdown.svelte | 9 +- packages/carta-md/src/lib/internal/carta.ts | 126 ++- .../src/lib/internal/components/Input.svelte | 39 +- .../carta-md/src/lib/internal/highlight.ts | 122 ++- packages/carta-md/src/routes/+page.svelte | 4 + packages/carta-md/src/routes/sample.md | 10 +- packages/carta-md/static/pic.jpg | Bin 0 -> 1504144 bytes packages/plugin-anchor/package.json | 4 +- packages/plugin-anchor/src/lib/default.css | 39 +- packages/plugin-anchor/src/lib/index.ts | 41 +- packages/plugin-anchor/src/lib/link.svg | 3 + packages/plugin-anchor/src/lib/slug.ts | 23 - .../plugin-anchor/src/routes/+page.svelte | 11 +- packages/plugin-code/package.json | 6 +- packages/plugin-code/src/index.ts | 110 +-- packages/plugin-emoji/package.json | 4 +- packages/plugin-emoji/src/lib/index.ts | 32 +- packages/plugin-math/package.json | 9 +- packages/plugin-math/src/index.ts | 99 +- packages/plugin-tikz/package.json | 12 +- packages/plugin-tikz/src/index.ts | 108 +-- pnpm-lock.yaml | 889 ++++++++++++++++-- 29 files changed, 1191 insertions(+), 526 deletions(-) create mode 100644 packages/carta-md/static/pic.jpg create mode 100644 packages/plugin-anchor/src/lib/link.svg delete mode 100644 packages/plugin-anchor/src/lib/slug.ts diff --git a/.vscode/settings.json b/.vscode/settings.json index 7ffe1d0..1cee4ab 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -5,12 +5,14 @@ "coldark", "dompurify", "flexsearch", + "Gemoji", "gruvbox", "Katex", "mdsvex", "oldschool", "rehype", "shiki", + "shikijs", "tikz", "tikzjax", "typeof" diff --git a/README.md b/README.md index 5832d66..45d1f17 100644 --- a/README.md +++ b/README.md @@ -15,8 +15,6 @@ [![Carta.png](https://i.postimg.cc/nV6DMXKM/Carta.png)](https://beartocode.github.io/carta/) -
-

Carta

Modern, lightweight, powerful Markdown Editor.

diff --git a/docs/src/lib/examples/DiscordExample.svelte b/docs/src/lib/examples/DiscordExample.svelte index cfc74be..0a60675 100644 --- a/docs/src/lib/examples/DiscordExample.svelte +++ b/docs/src/lib/examples/DiscordExample.svelte @@ -7,6 +7,7 @@ import '$lib/styles/discord.scss'; const carta = new Carta({ + sanitizer: false, disableIcons: true, extensions: [ emoji(), diff --git a/docs/src/lib/examples/GitHubExample.svelte b/docs/src/lib/examples/GitHubExample.svelte index 092f677..5de31c6 100644 --- a/docs/src/lib/examples/GitHubExample.svelte +++ b/docs/src/lib/examples/GitHubExample.svelte @@ -8,6 +8,7 @@ import '$lib/styles/github.scss'; const carta = new Carta({ + sanitizer: false, extensions: [ attachment({ async upload() { diff --git a/docs/src/lib/examples/MathStackExchangeExample.svelte b/docs/src/lib/examples/MathStackExchangeExample.svelte index 57e948b..c6057b1 100644 --- a/docs/src/lib/examples/MathStackExchangeExample.svelte +++ b/docs/src/lib/examples/MathStackExchangeExample.svelte @@ -8,6 +8,7 @@ import 'katex/dist/katex.min.css'; const carta = new Carta({ + sanitizer: false, extensions: [ math(), tikz({ diff --git a/packages/carta-md/README.md b/packages/carta-md/README.md index 6f32c52..f713164 100644 --- a/packages/carta-md/README.md +++ b/packages/carta-md/README.md @@ -15,8 +15,6 @@ [![Carta.png](https://i.postimg.cc/nV6DMXKM/Carta.png)](https://beartocode.github.io/carta/) -
-

Carta

Modern, lightweight, powerful Markdown Editor.

diff --git a/packages/carta-md/package.json b/packages/carta-md/package.json index 54d23ab..e1eeb05 100644 --- a/packages/carta-md/package.json +++ b/packages/carta-md/package.json @@ -35,8 +35,12 @@ }, "type": "module", "dependencies": { - "marked": "^9.1.5", - "shiki": "^1.2.4" + "rehype-stringify": "^10.0.0", + "remark-gfm": "^4.0.0", + "remark-parse": "^11.0.0", + "remark-rehype": "^11.1.0", + "shiki": "^1.3.0", + "unified": "^11.0.4" }, "peerDependencies": { "svelte": "^3.54.0 || ^4.0.0" diff --git a/packages/carta-md/src/lib/Markdown.svelte b/packages/carta-md/src/lib/Markdown.svelte index 3bd3d45..25d3971 100644 --- a/packages/carta-md/src/lib/Markdown.svelte +++ b/packages/carta-md/src/lib/Markdown.svelte @@ -1,6 +1,6 @@ `; + const script = /* html */ ``; // Simply appending the element does not work as the script is not executed // By doing the following we ensure that it is run. @@ -189,9 +180,6 @@ async function loadTikz(options?: TikzExtensionOptions) { document.addEventListener('tikzjax-load-finished', (e) => { const elem = e.target as SVGElement; - // Support old version - options?.postProcess && options.postProcess(elem); - if (options?.postProcessing) elem.outerHTML = options.postProcessing(elem.outerHTML); }); } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 443c019..885691f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -159,15 +159,27 @@ importers: packages/carta-md: dependencies: - marked: - specifier: ^9.1.5 - version: 9.1.5 + rehype-stringify: + specifier: ^10.0.0 + version: 10.0.0 + remark-gfm: + specifier: ^4.0.0 + version: 4.0.0 + remark-parse: + specifier: ^11.0.0 + version: 11.0.0 + remark-rehype: + specifier: ^11.1.0 + version: 11.1.0 shiki: - specifier: ^1.2.4 - version: 1.2.4 + specifier: ^1.3.0 + version: 1.3.0 svelte: specifier: ^3.54.0 || ^4.0.0 version: 4.2.2 + unified: + specifier: ^11.0.4 + version: 11.0.4 devDependencies: '@sveltejs/adapter-auto': specifier: ^3.1.1 @@ -196,9 +208,12 @@ importers: packages/plugin-anchor: dependencies: - slugify: - specifier: ^1.6.6 - version: 1.6.6 + rehype-autolink-headings: + specifier: ^7.1.0 + version: 7.1.0 + rehype-slug: + specifier: ^6.0.0 + version: 6.0.0 devDependencies: '@sveltejs/adapter-auto': specifier: ^3.1.1 @@ -281,9 +296,12 @@ importers: packages/plugin-code: dependencies: - marked-highlight: - specifier: ^2.0.6 - version: 2.0.6(marked@9.1.5) + '@shikijs/rehype': + specifier: ^1.3.0 + version: 1.3.0 + unified: + specifier: ^11.0.4 + version: 11.0.4 devDependencies: '@types/node': specifier: ^18.16.3 @@ -291,12 +309,6 @@ importers: carta-md: specifier: workspace:* version: link:../carta-md - marked: - specifier: ^9.1.5 - version: 9.1.5 - shiki: - specifier: ^1.2.4 - version: 1.2.4 typescript: specifier: ^5.0.4 version: 5.0.4 @@ -312,6 +324,9 @@ importers: node-emoji: specifier: ^1.11.0 version: 1.11.0 + remark-gemoji: + specifier: ^8.0.0 + version: 8.0.0 devDependencies: '@sveltejs/adapter-auto': specifier: ^3.1.1 @@ -355,19 +370,16 @@ importers: packages/plugin-math: dependencies: - katex: - specifier: ^0.16.10 - version: 0.16.10 + rehype-katex: + specifier: ^7.0.0 + version: 7.0.0 + remark-math: + specifier: ^6.0.0 + version: 6.0.0 devDependencies: - '@types/katex': - specifier: ^0.16.0 - version: 0.16.0 carta-md: specifier: workspace:* version: link:../carta-md - marked: - specifier: ^9.1.5 - version: 9.1.5 typescript: specifier: ^5.0.4 version: 5.0.4 @@ -419,22 +431,32 @@ importers: version: 5.1.6(@types/node@18.16.3)(sass@1.69.5) packages/plugin-tikz: + dependencies: + hast-util-from-dom: + specifier: ^5.0.0 + version: 5.0.0 + unist-util-visit: + specifier: ^5.0.0 + version: 5.0.0 devDependencies: + '@types/hast': + specifier: ^3.0.4 + version: 3.0.4 '@types/md5': specifier: ^2.3.2 version: 2.3.2 carta-md: specifier: workspace:* version: link:../carta-md - marked: - specifier: ^9.1.5 - version: 9.1.5 md5: specifier: ^2.3.0 version: 2.3.0 typescript: specifier: ^5.0.4 version: 5.0.4 + unified: + specifier: ^11.0.4 + version: 11.0.4 vite: specifier: ^5.1.6 version: 5.1.6(@types/node@18.16.3)(sass@1.69.5) @@ -1396,15 +1418,33 @@ packages: - supports-color dev: true - /@shikijs/core@1.2.4: - resolution: {integrity: sha512-ClaUWpt8oTzjcF0MM1P81AeWyzc1sNSJlAjMG80CbwqbFqXSNz+NpQVUC0icobt3sZn43Sn27M4pHD/Jmp3zHw==} + /@shikijs/core@1.3.0: + resolution: {integrity: sha512-7fedsBfuILDTBmrYZNFI8B6ATTxhQAasUHllHmjvSZPnoq4bULWoTpHwmuQvZ8Aq03/tAa2IGo6RXqWtHdWaCA==} + dev: false + + /@shikijs/rehype@1.3.0: + resolution: {integrity: sha512-CknEidx0ZTg3TeYAPU4ah8cr31a16neBbMyQ5kwAVdkloCe65uhQp+C/FEFs8NRir4eU5XCDA/+w2v5wnN6zgQ==} + dependencies: + '@shikijs/transformers': 1.3.0 + '@types/hast': 3.0.4 + hast-util-to-string: 3.0.0 + shiki: 1.3.0 + unified: 11.0.4 + unist-util-visit: 5.0.0 + dev: false + + /@shikijs/transformers@1.3.0: + resolution: {integrity: sha512-3mlpg2I9CjhjE96dEWQOGeCWoPcyTov3s4aAsHmgvnTHa8MBknEnCQy8/xivJPSpD+olqOqIEoHnLfbNJK29AA==} + dependencies: + shiki: 1.3.0 + dev: false /@sveltejs/adapter-auto@3.1.1(@sveltejs/kit@2.5.4): resolution: {integrity: sha512-6LeZft2Fo/4HfmLBi5CucMYmgRxgcETweQl/yQoZo/895K3S9YWYN4Sfm/IhwlIpbJp3QNvhKmwCHbsqQNYQpw==} peerDependencies: '@sveltejs/kit': ^2.0.0 dependencies: - '@sveltejs/kit': 2.5.4(@sveltejs/vite-plugin-svelte@3.0.2)(svelte@4.2.12)(vite@5.1.6) + '@sveltejs/kit': 2.5.4(@sveltejs/vite-plugin-svelte@3.0.2)(svelte@4.2.2)(vite@5.1.6) import-meta-resolve: 4.0.0 dev: true @@ -1627,6 +1667,12 @@ packages: resolution: {integrity: sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==} dev: true + /@types/debug@4.1.12: + resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==} + dependencies: + '@types/ms': 0.7.34 + dev: false + /@types/estree@1.0.1: resolution: {integrity: sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==} @@ -1637,11 +1683,10 @@ packages: resolution: {integrity: sha512-H5IXcRn96/gaDmo+rDl2aJuIJsob8dgOXDqf8K0t8rWZd1AFNaaspmRsElESiU+EWE33qfbFPgI0OC/B1g9FCA==} dev: true - /@types/hast@3.0.3: - resolution: {integrity: sha512-2fYGlaDy/qyLlhidX42wAH0KBi2TCjKMH8CHmBXgRlJ3Y+OXTiqsPQ6IWarZKwF1JoUcAJdPogv1d4b0COTpmQ==} + /@types/hast@3.0.4: + resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==} dependencies: '@types/unist': 3.0.2 - dev: true /@types/json-schema@7.0.15: resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} @@ -1649,16 +1694,25 @@ packages: /@types/katex@0.16.0: resolution: {integrity: sha512-hz+S3nV6Mym5xPbT9fnO8dDhBFQguMYpY0Ipxv06JMi1ORgnEM4M1ymWDUhUNer3ElLmT583opRo4RzxKmh9jw==} - dev: true /@types/md5@2.3.2: resolution: {integrity: sha512-v+JFDu96+UYJ3/UWzB0mEglIS//MZXgRaJ4ubUPwOM0gvLc/kcQ3TWNYwENEK7/EcXGQVrW8h/XqednSjBd/Og==} dev: true + /@types/mdast@4.0.3: + resolution: {integrity: sha512-LsjtqsyF+d2/yFOYaN22dHZI1Cpwkrj+g06G8+qtUKlhovPW89YhqSnfKtMbkgmEtYpH2gydRNULd6y8mciAFg==} + dependencies: + '@types/unist': 3.0.2 + dev: false + /@types/minimist@1.2.4: resolution: {integrity: sha512-Kfe/D3hxHTusnPNRbycJE1N77WHDsdS4AjUYIzlDzhDrS47NrwuL3YW4VITxwR7KCVpzwgy4Rbj829KSSQmwXQ==} dev: true + /@types/ms@0.7.34: + resolution: {integrity: sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==} + dev: false + /@types/node-emoji@1.8.2: resolution: {integrity: sha512-PfF1qL/9veo8BSHLV84C9ORNr3lHSlnWJ6yU8OdNufoftajeWHTLVbGHvp2B7e7DPDS9gMs6cfeSsqo5rqSitg==} dev: true @@ -1691,7 +1745,6 @@ packages: /@types/unist@3.0.2: resolution: {integrity: sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==} - dev: true /@typescript-eslint/eslint-plugin@6.10.0(@typescript-eslint/parser@6.10.0)(eslint@8.39.0)(typescript@5.3.3): resolution: {integrity: sha512-uoLj4g2OTL8rfUQVx2AFO1hp/zja1wABJq77P6IclQs6I/m9GLrm7jCdgzZkvWdDCQf1uEvoa8s8CupsgWQgVg==} @@ -1826,7 +1879,6 @@ packages: /@ungap/structured-clone@1.2.0: resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} - dev: true /@volar/language-core@1.11.1: resolution: {integrity: sha512-dOcNn3i9GgZAcJt43wuaEykSluAuOkQgzni1cuxLxTV0nJKanQztp7FxyswdRILaKH+P2XZMPRp2S4MV/pElCw==} @@ -2105,7 +2157,6 @@ packages: /bail@2.0.2: resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==} - dev: true /balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} @@ -2248,6 +2299,10 @@ packages: redeyed: 2.1.1 dev: true + /ccount@2.0.1: + resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} + dev: false + /chalk@2.4.2: resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} engines: {node: '>=4'} @@ -2270,6 +2325,18 @@ packages: engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} dev: true + /character-entities-html4@2.1.0: + resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==} + dev: false + + /character-entities-legacy@3.0.0: + resolution: {integrity: sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==} + dev: false + + /character-entities@2.0.2: + resolution: {integrity: sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==} + dev: false + /chardet@0.7.0: resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} dev: true @@ -2442,6 +2509,10 @@ packages: engines: {node: '>=0.1.90'} dev: true + /comma-separated-tokens@2.0.3: + resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==} + dev: false + /commander@10.0.1: resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==} engines: {node: '>=14'} @@ -2686,7 +2757,6 @@ packages: optional: true dependencies: ms: 2.1.2 - dev: true /decamelize-keys@1.1.1: resolution: {integrity: sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==} @@ -2701,6 +2771,12 @@ packages: engines: {node: '>=0.10.0'} dev: true + /decode-named-character-reference@1.0.2: + resolution: {integrity: sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==} + dependencies: + character-entities: 2.0.2 + dev: false + /dedent-js@1.0.1: resolution: {integrity: sha512-OUepMozQULMLUmhxS95Vudo0jb0UchLimi3+pQ2plj61Fcy8axbP9hbiD4Sz6DPqn6XG3kfmziVfQ1rSys5AJQ==} dev: true @@ -2769,7 +2845,6 @@ packages: resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} dependencies: dequal: 2.0.3 - dev: true /didyoumean@1.2.2: resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} @@ -2831,7 +2906,6 @@ packages: /entities@4.5.0: resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} engines: {node: '>=0.12'} - dev: true /env-ci@8.0.0: resolution: {integrity: sha512-W+3BqGZozFua9MPeXpmTm5eYEBtGgL76jGu/pwMVp/L8PdECSCEWaIp7d4Mw7kuUrbUldK0oV0bNd6ZZjLiMiA==} @@ -2900,7 +2974,6 @@ packages: /escape-string-regexp@5.0.0: resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} engines: {node: '>=12'} - dev: true /eslint-compat-utils@0.1.2(eslint@8.39.0): resolution: {integrity: sha512-Jia4JDldWnFNIru1Ehx1H5s9/yxiRHY/TimCuUc0jNexew3cF1gI6CYZil1ociakfWO3rRqFjl1mskBblB3RYg==} @@ -3135,7 +3208,6 @@ packages: /extend@3.0.2: resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} - dev: true /external-editor@3.1.0: resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} @@ -3373,6 +3445,10 @@ packages: resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} dev: true + /gemoji@8.1.0: + resolution: {integrity: sha512-HA4Gx59dw2+tn+UAa7XEV4ufUKI4fH1KgcbenVA9YKSj1QJTT0xh5Mwv5HMFNN3l2OtUe3ZIfuRwSyZS5pLIWw==} + dev: false + /get-caller-file@2.0.5: resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} engines: {node: 6.* || 8.* || >= 10.*} @@ -3401,7 +3477,6 @@ packages: /github-slugger@2.0.0: resolution: {integrity: sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==} - dev: true /glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} @@ -3569,23 +3644,139 @@ packages: function-bind: 1.1.1 dev: true + /hast-util-from-dom@5.0.0: + resolution: {integrity: sha512-d6235voAp/XR3Hh5uy7aGLbM3S4KamdW0WEgOaU1YoewnuYw4HXb5eRtv9g65m/RFGEfUY1Mw4UqCc5Y8L4Stg==} + dependencies: + '@types/hast': 3.0.4 + hastscript: 8.0.0 + web-namespaces: 2.0.1 + dev: false + + /hast-util-from-html-isomorphic@2.0.0: + resolution: {integrity: sha512-zJfpXq44yff2hmE0XmwEOzdWin5xwH+QIhMLOScpX91e/NSGPsAzNCvLQDIEPyO2TXi+lBmU6hjLIhV8MwP2kw==} + dependencies: + '@types/hast': 3.0.4 + hast-util-from-dom: 5.0.0 + hast-util-from-html: 2.0.1 + unist-util-remove-position: 5.0.0 + dev: false + + /hast-util-from-html@2.0.1: + resolution: {integrity: sha512-RXQBLMl9kjKVNkJTIO6bZyb2n+cUH8LFaSSzo82jiLT6Tfc+Pt7VQCS+/h3YwG4jaNE2TA2sdJisGWR+aJrp0g==} + dependencies: + '@types/hast': 3.0.4 + devlop: 1.1.0 + hast-util-from-parse5: 8.0.1 + parse5: 7.1.2 + vfile: 6.0.1 + vfile-message: 4.0.2 + dev: false + + /hast-util-from-parse5@8.0.1: + resolution: {integrity: sha512-Er/Iixbc7IEa7r/XLtuG52zoqn/b3Xng/w6aZQ0xGVxzhw5xUFxcRqdPzP6yFi/4HBYRaifaI5fQ1RH8n0ZeOQ==} + dependencies: + '@types/hast': 3.0.4 + '@types/unist': 3.0.2 + devlop: 1.1.0 + hastscript: 8.0.0 + property-information: 6.5.0 + vfile: 6.0.1 + vfile-location: 5.0.2 + web-namespaces: 2.0.1 + dev: false + /hast-util-heading-rank@3.0.0: resolution: {integrity: sha512-EJKb8oMUXVHcWZTDepnr+WNbfnXKFNf9duMesmr4S8SXTJBJ9M4Yok08pu9vxdJwdlGRhVumk9mEhkEvKGifwA==} dependencies: - '@types/hast': 3.0.3 - dev: true + '@types/hast': 3.0.4 /hast-util-is-element@3.0.0: resolution: {integrity: sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==} dependencies: - '@types/hast': 3.0.3 - dev: true + '@types/hast': 3.0.4 + + /hast-util-parse-selector@4.0.0: + resolution: {integrity: sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==} + dependencies: + '@types/hast': 3.0.4 + dev: false + + /hast-util-raw@9.0.2: + resolution: {integrity: sha512-PldBy71wO9Uq1kyaMch9AHIghtQvIwxBUkv823pKmkTM3oV1JxtsTNYdevMxvUHqcnOAuO65JKU2+0NOxc2ksA==} + dependencies: + '@types/hast': 3.0.4 + '@types/unist': 3.0.2 + '@ungap/structured-clone': 1.2.0 + hast-util-from-parse5: 8.0.1 + hast-util-to-parse5: 8.0.0 + html-void-elements: 3.0.0 + mdast-util-to-hast: 13.1.0 + parse5: 7.1.2 + unist-util-position: 5.0.0 + unist-util-visit: 5.0.0 + vfile: 6.0.1 + web-namespaces: 2.0.1 + zwitch: 2.0.4 + dev: false + + /hast-util-to-html@9.0.1: + resolution: {integrity: sha512-hZOofyZANbyWo+9RP75xIDV/gq+OUKx+T46IlwERnKmfpwp81XBFbT9mi26ws+SJchA4RVUQwIBJpqEOBhMzEQ==} + dependencies: + '@types/hast': 3.0.4 + '@types/unist': 3.0.2 + ccount: 2.0.1 + comma-separated-tokens: 2.0.3 + hast-util-raw: 9.0.2 + hast-util-whitespace: 3.0.0 + html-void-elements: 3.0.0 + mdast-util-to-hast: 13.1.0 + property-information: 6.5.0 + space-separated-tokens: 2.0.2 + stringify-entities: 4.0.4 + zwitch: 2.0.4 + dev: false + + /hast-util-to-parse5@8.0.0: + resolution: {integrity: sha512-3KKrV5ZVI8if87DVSi1vDeByYrkGzg4mEfeu4alwgmmIeARiBLKCZS2uw5Gb6nU9x9Yufyj3iudm6i7nl52PFw==} + dependencies: + '@types/hast': 3.0.4 + comma-separated-tokens: 2.0.3 + devlop: 1.1.0 + property-information: 6.5.0 + space-separated-tokens: 2.0.2 + web-namespaces: 2.0.1 + zwitch: 2.0.4 + dev: false /hast-util-to-string@3.0.0: resolution: {integrity: sha512-OGkAxX1Ua3cbcW6EJ5pT/tslVb90uViVkcJ4ZZIMW/R33DX/AkcJcRrPebPwJkHYwlDHXz4aIwvAAaAdtrACFA==} dependencies: - '@types/hast': 3.0.3 - dev: true + '@types/hast': 3.0.4 + + /hast-util-to-text@4.0.1: + resolution: {integrity: sha512-RHL7Vo2n06ZocCFWqmbyhZ1pCYX/mSKdywt9YD5U6Hquu5syV+dImCXFKLFt02JoK5QxkQFS0PoVdFdPXuPffQ==} + dependencies: + '@types/hast': 3.0.4 + '@types/unist': 3.0.2 + hast-util-is-element: 3.0.0 + unist-util-find-after: 5.0.0 + dev: false + + /hast-util-whitespace@3.0.0: + resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==} + dependencies: + '@types/hast': 3.0.4 + dev: false + + /hastscript@8.0.0: + resolution: {integrity: sha512-dMOtzCEd3ABUeSIISmrETiKuyydk1w0pa+gE/uormcTpSYuaNJPbX1NU3JLyscSLjwAQM8bWMhhIlnCqnRvDTw==} + dependencies: + '@types/hast': 3.0.4 + comma-separated-tokens: 2.0.3 + hast-util-parse-selector: 4.0.0 + property-information: 6.5.0 + space-separated-tokens: 2.0.2 + dev: false /he@1.2.0: resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} @@ -3622,6 +3813,10 @@ packages: lru-cache: 7.18.3 dev: true + /html-void-elements@3.0.0: + resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==} + dev: false + /http-proxy-agent@7.0.0: resolution: {integrity: sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ==} engines: {node: '>= 14'} @@ -3852,7 +4047,6 @@ packages: /is-plain-obj@4.1.0: resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} engines: {node: '>=12'} - dev: true /is-plain-object@5.0.0: resolution: {integrity: sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==} @@ -4219,6 +4413,10 @@ packages: wrap-ansi: 6.2.0 dev: true + /longest-streak@3.1.0: + resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==} + dev: false + /longest@2.0.1: resolution: {integrity: sha512-Ajzxb8CM6WAnFjgiloPsI3bF+WCxcvhdIG3KNA2KN962+tdBsHcuQ4k4qX/EcS/2CRkcc0iAkR956Nib6aXU/Q==} engines: {node: '>=0.10.0'} @@ -4275,12 +4473,8 @@ packages: engines: {node: '>=8'} dev: true - /marked-highlight@2.0.6(marked@9.1.5): - resolution: {integrity: sha512-xjA/C6xgXAfkkYg+YHnxdjmgFyTDtqqu8KbZiqh+COJ7PuzR15kqa+rPrs6pf/2jExXtG1jyCFUHmv9s0Bi/dQ==} - peerDependencies: - marked: '>=4 <10' - dependencies: - marked: 9.1.5 + /markdown-table@3.0.3: + resolution: {integrity: sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw==} dev: false /marked-terminal@5.2.0(marked@4.3.0): @@ -4308,6 +4502,7 @@ packages: resolution: {integrity: sha512-14QG3shv8Kg/xc0Yh6TNkMj90wXH9mmldi5941I2OevfJ/FQAFLEwtwU2/FfgSAOMlWHrEukWSGQf8MiVYNG2A==} engines: {node: '>= 16'} hasBin: true + dev: true /md5@2.3.0: resolution: {integrity: sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==} @@ -4317,6 +4512,157 @@ packages: is-buffer: 1.1.6 dev: true + /mdast-util-find-and-replace@3.0.1: + resolution: {integrity: sha512-SG21kZHGC3XRTSUhtofZkBzZTJNM5ecCi0SK2IMKmSXR8vO3peL+kb1O0z7Zl83jKtutG4k5Wv/W7V3/YHvzPA==} + dependencies: + '@types/mdast': 4.0.3 + escape-string-regexp: 5.0.0 + unist-util-is: 6.0.0 + unist-util-visit-parents: 6.0.1 + dev: false + + /mdast-util-from-markdown@2.0.0: + resolution: {integrity: sha512-n7MTOr/z+8NAX/wmhhDji8O3bRvPTV/U0oTCaZJkjhPSKTPhS3xufVhKGF8s1pJ7Ox4QgoIU7KHseh09S+9rTA==} + dependencies: + '@types/mdast': 4.0.3 + '@types/unist': 3.0.2 + decode-named-character-reference: 1.0.2 + devlop: 1.1.0 + mdast-util-to-string: 4.0.0 + micromark: 4.0.0 + micromark-util-decode-numeric-character-reference: 2.0.1 + micromark-util-decode-string: 2.0.0 + micromark-util-normalize-identifier: 2.0.0 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + unist-util-stringify-position: 4.0.0 + transitivePeerDependencies: + - supports-color + dev: false + + /mdast-util-gfm-autolink-literal@2.0.0: + resolution: {integrity: sha512-FyzMsduZZHSc3i0Px3PQcBT4WJY/X/RCtEJKuybiC6sjPqLv7h1yqAkmILZtuxMSsUyaLUWNp71+vQH2zqp5cg==} + dependencies: + '@types/mdast': 4.0.3 + ccount: 2.0.1 + devlop: 1.1.0 + mdast-util-find-and-replace: 3.0.1 + micromark-util-character: 2.1.0 + dev: false + + /mdast-util-gfm-footnote@2.0.0: + resolution: {integrity: sha512-5jOT2boTSVkMnQ7LTrd6n/18kqwjmuYqo7JUPe+tRCY6O7dAuTFMtTPauYYrMPpox9hlN0uOx/FL8XvEfG9/mQ==} + dependencies: + '@types/mdast': 4.0.3 + devlop: 1.1.0 + mdast-util-from-markdown: 2.0.0 + mdast-util-to-markdown: 2.1.0 + micromark-util-normalize-identifier: 2.0.0 + transitivePeerDependencies: + - supports-color + dev: false + + /mdast-util-gfm-strikethrough@2.0.0: + resolution: {integrity: sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==} + dependencies: + '@types/mdast': 4.0.3 + mdast-util-from-markdown: 2.0.0 + mdast-util-to-markdown: 2.1.0 + transitivePeerDependencies: + - supports-color + dev: false + + /mdast-util-gfm-table@2.0.0: + resolution: {integrity: sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==} + dependencies: + '@types/mdast': 4.0.3 + devlop: 1.1.0 + markdown-table: 3.0.3 + mdast-util-from-markdown: 2.0.0 + mdast-util-to-markdown: 2.1.0 + transitivePeerDependencies: + - supports-color + dev: false + + /mdast-util-gfm-task-list-item@2.0.0: + resolution: {integrity: sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==} + dependencies: + '@types/mdast': 4.0.3 + devlop: 1.1.0 + mdast-util-from-markdown: 2.0.0 + mdast-util-to-markdown: 2.1.0 + transitivePeerDependencies: + - supports-color + dev: false + + /mdast-util-gfm@3.0.0: + resolution: {integrity: sha512-dgQEX5Amaq+DuUqf26jJqSK9qgixgd6rYDHAv4aTBuA92cTknZlKpPfa86Z/s8Dj8xsAQpFfBmPUHWJBWqS4Bw==} + dependencies: + mdast-util-from-markdown: 2.0.0 + mdast-util-gfm-autolink-literal: 2.0.0 + mdast-util-gfm-footnote: 2.0.0 + mdast-util-gfm-strikethrough: 2.0.0 + mdast-util-gfm-table: 2.0.0 + mdast-util-gfm-task-list-item: 2.0.0 + mdast-util-to-markdown: 2.1.0 + transitivePeerDependencies: + - supports-color + dev: false + + /mdast-util-math@3.0.0: + resolution: {integrity: sha512-Tl9GBNeG/AhJnQM221bJR2HPvLOSnLE/T9cJI9tlc6zwQk2nPk/4f0cHkOdEixQPC/j8UtKDdITswvLAy1OZ1w==} + dependencies: + '@types/hast': 3.0.4 + '@types/mdast': 4.0.3 + devlop: 1.1.0 + longest-streak: 3.1.0 + mdast-util-from-markdown: 2.0.0 + mdast-util-to-markdown: 2.1.0 + unist-util-remove-position: 5.0.0 + transitivePeerDependencies: + - supports-color + dev: false + + /mdast-util-phrasing@4.1.0: + resolution: {integrity: sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==} + dependencies: + '@types/mdast': 4.0.3 + unist-util-is: 6.0.0 + dev: false + + /mdast-util-to-hast@13.1.0: + resolution: {integrity: sha512-/e2l/6+OdGp/FB+ctrJ9Avz71AN/GRH3oi/3KAx/kMnoUsD6q0woXlDT8lLEeViVKE7oZxE7RXzvO3T8kF2/sA==} + dependencies: + '@types/hast': 3.0.4 + '@types/mdast': 4.0.3 + '@ungap/structured-clone': 1.2.0 + devlop: 1.1.0 + micromark-util-sanitize-uri: 2.0.0 + trim-lines: 3.0.1 + unist-util-position: 5.0.0 + unist-util-visit: 5.0.0 + vfile: 6.0.1 + dev: false + + /mdast-util-to-markdown@2.1.0: + resolution: {integrity: sha512-SR2VnIEdVNCJbP6y7kVTJgPLifdr8WEU440fQec7qHoHOUz/oJ2jmNRqdDQ3rbiStOXb2mCDGTuwsK5OPUgYlQ==} + dependencies: + '@types/mdast': 4.0.3 + '@types/unist': 3.0.2 + longest-streak: 3.1.0 + mdast-util-phrasing: 4.1.0 + mdast-util-to-string: 4.0.0 + micromark-util-decode-string: 2.0.0 + unist-util-visit: 5.0.0 + zwitch: 2.0.4 + dev: false + + /mdast-util-to-string@4.0.0: + resolution: {integrity: sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==} + dependencies: + '@types/mdast': 4.0.3 + dev: false + /mdn-data@2.0.30: resolution: {integrity: sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==} @@ -4362,6 +4708,265 @@ packages: resolution: {integrity: sha512-jz+Cfrg9GWOZbQAnDQ4hlVnQky+341Yk5ru8bZSe6sIDTCIg8n9i/u7hSQGSVOF3C7lH6mGtqjkiT9G4wFLL0w==} dev: true + /micromark-core-commonmark@2.0.0: + resolution: {integrity: sha512-jThOz/pVmAYUtkroV3D5c1osFXAMv9e0ypGDOIZuCeAe91/sD6BoE2Sjzt30yuXtwOYUmySOhMas/PVyh02itA==} + dependencies: + decode-named-character-reference: 1.0.2 + devlop: 1.1.0 + micromark-factory-destination: 2.0.0 + micromark-factory-label: 2.0.0 + micromark-factory-space: 2.0.0 + micromark-factory-title: 2.0.0 + micromark-factory-whitespace: 2.0.0 + micromark-util-character: 2.1.0 + micromark-util-chunked: 2.0.0 + micromark-util-classify-character: 2.0.0 + micromark-util-html-tag-name: 2.0.0 + micromark-util-normalize-identifier: 2.0.0 + micromark-util-resolve-all: 2.0.0 + micromark-util-subtokenize: 2.0.0 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + dev: false + + /micromark-extension-gfm-autolink-literal@2.0.0: + resolution: {integrity: sha512-rTHfnpt/Q7dEAK1Y5ii0W8bhfJlVJFnJMHIPisfPK3gpVNuOP0VnRl96+YJ3RYWV/P4gFeQoGKNlT3RhuvpqAg==} + dependencies: + micromark-util-character: 2.1.0 + micromark-util-sanitize-uri: 2.0.0 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + dev: false + + /micromark-extension-gfm-footnote@2.0.0: + resolution: {integrity: sha512-6Rzu0CYRKDv3BfLAUnZsSlzx3ak6HAoI85KTiijuKIz5UxZxbUI+pD6oHgw+6UtQuiRwnGRhzMmPRv4smcz0fg==} + dependencies: + devlop: 1.1.0 + micromark-core-commonmark: 2.0.0 + micromark-factory-space: 2.0.0 + micromark-util-character: 2.1.0 + micromark-util-normalize-identifier: 2.0.0 + micromark-util-sanitize-uri: 2.0.0 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + dev: false + + /micromark-extension-gfm-strikethrough@2.0.0: + resolution: {integrity: sha512-c3BR1ClMp5fxxmwP6AoOY2fXO9U8uFMKs4ADD66ahLTNcwzSCyRVU4k7LPV5Nxo/VJiR4TdzxRQY2v3qIUceCw==} + dependencies: + devlop: 1.1.0 + micromark-util-chunked: 2.0.0 + micromark-util-classify-character: 2.0.0 + micromark-util-resolve-all: 2.0.0 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + dev: false + + /micromark-extension-gfm-table@2.0.0: + resolution: {integrity: sha512-PoHlhypg1ItIucOaHmKE8fbin3vTLpDOUg8KAr8gRCF1MOZI9Nquq2i/44wFvviM4WuxJzc3demT8Y3dkfvYrw==} + dependencies: + devlop: 1.1.0 + micromark-factory-space: 2.0.0 + micromark-util-character: 2.1.0 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + dev: false + + /micromark-extension-gfm-tagfilter@2.0.0: + resolution: {integrity: sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==} + dependencies: + micromark-util-types: 2.0.0 + dev: false + + /micromark-extension-gfm-task-list-item@2.0.1: + resolution: {integrity: sha512-cY5PzGcnULaN5O7T+cOzfMoHjBW7j+T9D2sucA5d/KbsBTPcYdebm9zUd9zzdgJGCwahV+/W78Z3nbulBYVbTw==} + dependencies: + devlop: 1.1.0 + micromark-factory-space: 2.0.0 + micromark-util-character: 2.1.0 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + dev: false + + /micromark-extension-gfm@3.0.0: + resolution: {integrity: sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==} + dependencies: + micromark-extension-gfm-autolink-literal: 2.0.0 + micromark-extension-gfm-footnote: 2.0.0 + micromark-extension-gfm-strikethrough: 2.0.0 + micromark-extension-gfm-table: 2.0.0 + micromark-extension-gfm-tagfilter: 2.0.0 + micromark-extension-gfm-task-list-item: 2.0.1 + micromark-util-combine-extensions: 2.0.0 + micromark-util-types: 2.0.0 + dev: false + + /micromark-extension-math@3.0.0: + resolution: {integrity: sha512-iJ2Q28vBoEovLN5o3GO12CpqorQRYDPT+p4zW50tGwTfJB+iv/VnB6Ini+gqa24K97DwptMBBIvVX6Bjk49oyQ==} + dependencies: + '@types/katex': 0.16.0 + devlop: 1.1.0 + katex: 0.16.10 + micromark-factory-space: 2.0.0 + micromark-util-character: 2.1.0 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + dev: false + + /micromark-factory-destination@2.0.0: + resolution: {integrity: sha512-j9DGrQLm/Uhl2tCzcbLhy5kXsgkHUrjJHg4fFAeoMRwJmJerT9aw4FEhIbZStWN8A3qMwOp1uzHr4UL8AInxtA==} + dependencies: + micromark-util-character: 2.1.0 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + dev: false + + /micromark-factory-label@2.0.0: + resolution: {integrity: sha512-RR3i96ohZGde//4WSe/dJsxOX6vxIg9TimLAS3i4EhBAFx8Sm5SmqVfR8E87DPSR31nEAjZfbt91OMZWcNgdZw==} + dependencies: + devlop: 1.1.0 + micromark-util-character: 2.1.0 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + dev: false + + /micromark-factory-space@2.0.0: + resolution: {integrity: sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==} + dependencies: + micromark-util-character: 2.1.0 + micromark-util-types: 2.0.0 + dev: false + + /micromark-factory-title@2.0.0: + resolution: {integrity: sha512-jY8CSxmpWLOxS+t8W+FG3Xigc0RDQA9bKMY/EwILvsesiRniiVMejYTE4wumNc2f4UbAa4WsHqe3J1QS1sli+A==} + dependencies: + micromark-factory-space: 2.0.0 + micromark-util-character: 2.1.0 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + dev: false + + /micromark-factory-whitespace@2.0.0: + resolution: {integrity: sha512-28kbwaBjc5yAI1XadbdPYHX/eDnqaUFVikLwrO7FDnKG7lpgxnvk/XGRhX/PN0mOZ+dBSZ+LgunHS+6tYQAzhA==} + dependencies: + micromark-factory-space: 2.0.0 + micromark-util-character: 2.1.0 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + dev: false + + /micromark-util-character@2.1.0: + resolution: {integrity: sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==} + dependencies: + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + dev: false + + /micromark-util-chunked@2.0.0: + resolution: {integrity: sha512-anK8SWmNphkXdaKgz5hJvGa7l00qmcaUQoMYsBwDlSKFKjc6gjGXPDw3FNL3Nbwq5L8gE+RCbGqTw49FK5Qyvg==} + dependencies: + micromark-util-symbol: 2.0.0 + dev: false + + /micromark-util-classify-character@2.0.0: + resolution: {integrity: sha512-S0ze2R9GH+fu41FA7pbSqNWObo/kzwf8rN/+IGlW/4tC6oACOs8B++bh+i9bVyNnwCcuksbFwsBme5OCKXCwIw==} + dependencies: + micromark-util-character: 2.1.0 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + dev: false + + /micromark-util-combine-extensions@2.0.0: + resolution: {integrity: sha512-vZZio48k7ON0fVS3CUgFatWHoKbbLTK/rT7pzpJ4Bjp5JjkZeasRfrS9wsBdDJK2cJLHMckXZdzPSSr1B8a4oQ==} + dependencies: + micromark-util-chunked: 2.0.0 + micromark-util-types: 2.0.0 + dev: false + + /micromark-util-decode-numeric-character-reference@2.0.1: + resolution: {integrity: sha512-bmkNc7z8Wn6kgjZmVHOX3SowGmVdhYS7yBpMnuMnPzDq/6xwVA604DuOXMZTO1lvq01g+Adfa0pE2UKGlxL1XQ==} + dependencies: + micromark-util-symbol: 2.0.0 + dev: false + + /micromark-util-decode-string@2.0.0: + resolution: {integrity: sha512-r4Sc6leeUTn3P6gk20aFMj2ntPwn6qpDZqWvYmAG6NgvFTIlj4WtrAudLi65qYoaGdXYViXYw2pkmn7QnIFasA==} + dependencies: + decode-named-character-reference: 1.0.2 + micromark-util-character: 2.1.0 + micromark-util-decode-numeric-character-reference: 2.0.1 + micromark-util-symbol: 2.0.0 + dev: false + + /micromark-util-encode@2.0.0: + resolution: {integrity: sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA==} + dev: false + + /micromark-util-html-tag-name@2.0.0: + resolution: {integrity: sha512-xNn4Pqkj2puRhKdKTm8t1YHC/BAjx6CEwRFXntTaRf/x16aqka6ouVoutm+QdkISTlT7e2zU7U4ZdlDLJd2Mcw==} + dev: false + + /micromark-util-normalize-identifier@2.0.0: + resolution: {integrity: sha512-2xhYT0sfo85FMrUPtHcPo2rrp1lwbDEEzpx7jiH2xXJLqBuy4H0GgXk5ToU8IEwoROtXuL8ND0ttVa4rNqYK3w==} + dependencies: + micromark-util-symbol: 2.0.0 + dev: false + + /micromark-util-resolve-all@2.0.0: + resolution: {integrity: sha512-6KU6qO7DZ7GJkaCgwBNtplXCvGkJToU86ybBAUdavvgsCiG8lSSvYxr9MhwmQ+udpzywHsl4RpGJsYWG1pDOcA==} + dependencies: + micromark-util-types: 2.0.0 + dev: false + + /micromark-util-sanitize-uri@2.0.0: + resolution: {integrity: sha512-WhYv5UEcZrbAtlsnPuChHUAsu/iBPOVaEVsntLBIdpibO0ddy8OzavZz3iL2xVvBZOpolujSliP65Kq0/7KIYw==} + dependencies: + micromark-util-character: 2.1.0 + micromark-util-encode: 2.0.0 + micromark-util-symbol: 2.0.0 + dev: false + + /micromark-util-subtokenize@2.0.0: + resolution: {integrity: sha512-vc93L1t+gpR3p8jxeVdaYlbV2jTYteDje19rNSS/H5dlhxUYll5Fy6vJ2cDwP8RnsXi818yGty1ayP55y3W6fg==} + dependencies: + devlop: 1.1.0 + micromark-util-chunked: 2.0.0 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + dev: false + + /micromark-util-symbol@2.0.0: + resolution: {integrity: sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==} + dev: false + + /micromark-util-types@2.0.0: + resolution: {integrity: sha512-oNh6S2WMHWRZrmutsRmDDfkzKtxF+bc2VxLC9dvtrDIRFln627VsFP6fLMgTryGDljgLPjkrzQSDcPrjPyDJ5w==} + dev: false + + /micromark@4.0.0: + resolution: {integrity: sha512-o/sd0nMof8kYff+TqcDx3VSrgBTcZpSvYcAHIfHhv5VAuNmisCxjhx6YmxS8PFEpb9z5WKWKPdzf0jM23ro3RQ==} + dependencies: + '@types/debug': 4.1.12 + debug: 4.3.4 + decode-named-character-reference: 1.0.2 + devlop: 1.1.0 + micromark-core-commonmark: 2.0.0 + micromark-factory-space: 2.0.0 + micromark-util-character: 2.1.0 + micromark-util-chunked: 2.0.0 + micromark-util-combine-extensions: 2.0.0 + micromark-util-decode-numeric-character-reference: 2.0.1 + micromark-util-encode: 2.0.0 + micromark-util-normalize-identifier: 2.0.0 + micromark-util-resolve-all: 2.0.0 + micromark-util-sanitize-uri: 2.0.0 + micromark-util-subtokenize: 2.0.0 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + transitivePeerDependencies: + - supports-color + dev: false + /micromatch@4.0.5: resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} engines: {node: '>=8.6'} @@ -4483,7 +5088,6 @@ packages: /ms@2.1.2: resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} - dev: true /muggle-string@0.3.1: resolution: {integrity: sha512-ckmWDJjphvd/FvZawgygcUeQCxzvohjFO5RxTjj4eq8kw359gFF3E1brjfI+viLMxss5JrHTDRHZvu2/tuy0Qg==} @@ -4939,6 +5543,12 @@ packages: engines: {node: '>=0.10.0'} dev: true + /parse5@7.1.2: + resolution: {integrity: sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==} + dependencies: + entities: 4.5.0 + dev: false + /pascal-case@3.1.2: resolution: {integrity: sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==} dependencies: @@ -5260,6 +5870,10 @@ packages: resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} dev: true + /property-information@6.5.0: + resolution: {integrity: sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==} + dev: false + /proto-list@1.2.4: resolution: {integrity: sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==} dev: true @@ -5415,23 +6029,102 @@ packages: /rehype-autolink-headings@7.1.0: resolution: {integrity: sha512-rItO/pSdvnvsP4QRB1pmPiNHUskikqtPojZKJPPPAVx9Hj8i8TwMBhofrrAYRhYOOBZH9tgmG5lPqDLuIWPWmw==} dependencies: - '@types/hast': 3.0.3 + '@types/hast': 3.0.4 '@ungap/structured-clone': 1.2.0 hast-util-heading-rank: 3.0.0 hast-util-is-element: 3.0.0 unified: 11.0.4 unist-util-visit: 5.0.0 - dev: true + + /rehype-katex@7.0.0: + resolution: {integrity: sha512-h8FPkGE00r2XKU+/acgqwWUlyzve1IiOKwsEkg4pDL3k48PiE0Pt+/uLtVHDVkN1yA4iurZN6UES8ivHVEQV6Q==} + dependencies: + '@types/hast': 3.0.4 + '@types/katex': 0.16.0 + hast-util-from-html-isomorphic: 2.0.0 + hast-util-to-text: 4.0.1 + katex: 0.16.10 + unist-util-visit-parents: 6.0.1 + vfile: 6.0.1 + dev: false /rehype-slug@6.0.0: resolution: {integrity: sha512-lWyvf/jwu+oS5+hL5eClVd3hNdmwM1kAC0BUvEGD19pajQMIzcNUd/k9GsfQ+FfECvX+JE+e9/btsKH0EjJT6A==} dependencies: - '@types/hast': 3.0.3 + '@types/hast': 3.0.4 github-slugger: 2.0.0 hast-util-heading-rank: 3.0.0 hast-util-to-string: 3.0.0 unist-util-visit: 5.0.0 - dev: true + + /rehype-stringify@10.0.0: + resolution: {integrity: sha512-1TX1i048LooI9QoecrXy7nGFFbFSufxVRAfc6Y9YMRAi56l+oB0zP51mLSV312uRuvVLPV1opSlJmslozR1XHQ==} + dependencies: + '@types/hast': 3.0.4 + hast-util-to-html: 9.0.1 + unified: 11.0.4 + dev: false + + /remark-gemoji@8.0.0: + resolution: {integrity: sha512-/fL9rc72FYwFGtOKcT+QeQdx9Q9t5v4N6KLXSDOTEgaedzK85I9judBqB2eqz+g4b0ERMejlwSOuPK+wket6aA==} + dependencies: + '@types/mdast': 4.0.3 + gemoji: 8.1.0 + mdast-util-find-and-replace: 3.0.1 + dev: false + + /remark-gfm@4.0.0: + resolution: {integrity: sha512-U92vJgBPkbw4Zfu/IiW2oTZLSL3Zpv+uI7My2eq8JxKgqraFdU8YUGicEJCEgSbeaG+QDFqIcwwfMTOEelPxuA==} + dependencies: + '@types/mdast': 4.0.3 + mdast-util-gfm: 3.0.0 + micromark-extension-gfm: 3.0.0 + remark-parse: 11.0.0 + remark-stringify: 11.0.0 + unified: 11.0.4 + transitivePeerDependencies: + - supports-color + dev: false + + /remark-math@6.0.0: + resolution: {integrity: sha512-MMqgnP74Igy+S3WwnhQ7kqGlEerTETXMvJhrUzDikVZ2/uogJCb+WHUg97hK9/jcfc0dkD73s3LN8zU49cTEtA==} + dependencies: + '@types/mdast': 4.0.3 + mdast-util-math: 3.0.0 + micromark-extension-math: 3.0.0 + unified: 11.0.4 + transitivePeerDependencies: + - supports-color + dev: false + + /remark-parse@11.0.0: + resolution: {integrity: sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==} + dependencies: + '@types/mdast': 4.0.3 + mdast-util-from-markdown: 2.0.0 + micromark-util-types: 2.0.0 + unified: 11.0.4 + transitivePeerDependencies: + - supports-color + dev: false + + /remark-rehype@11.1.0: + resolution: {integrity: sha512-z3tJrAs2kIs1AqIIy6pzHmAHlF1hWQ+OdY4/hv+Wxe35EhyLKcajL33iUEn3ScxtFox9nUvRufR/Zre8Q08H/g==} + dependencies: + '@types/hast': 3.0.4 + '@types/mdast': 4.0.3 + mdast-util-to-hast: 13.1.0 + unified: 11.0.4 + vfile: 6.0.1 + dev: false + + /remark-stringify@11.0.0: + resolution: {integrity: sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==} + dependencies: + '@types/mdast': 4.0.3 + mdast-util-to-markdown: 2.1.0 + unified: 11.0.4 + dev: false /require-directory@2.1.1: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} @@ -5736,10 +6429,11 @@ packages: engines: {node: '>=8'} dev: true - /shiki@1.2.4: - resolution: {integrity: sha512-Q9n9jKiOjJCRPztA9POn3/uZXNySHDNKAsPNpmtHDcFyi6ZQhx5vQKZW3Nhrwn8TWW3RudSRk66zqY603EZDeg==} + /shiki@1.3.0: + resolution: {integrity: sha512-9aNdQy/etMXctnPzsje1h1XIGm9YfRcSksKOGqZWXA/qP9G18/8fpz5Bjpma8bOgz3tqIpjERAd6/lLjFyzoww==} dependencies: - '@shikijs/core': 1.2.4 + '@shikijs/core': 1.3.0 + dev: false /signal-exit@3.0.7: resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} @@ -5799,11 +6493,6 @@ packages: is-fullwidth-code-point: 4.0.0 dev: true - /slugify@1.6.6: - resolution: {integrity: sha512-h+z7HKHYXj6wJU+AnS/+IH8Uh9fdcX1Lrhg1/VMdf9PwoBQXFcXiAdsy2tSK0P6gKwJLXp02r90ahUCqHk9rrw==} - engines: {node: '>=8.0.0'} - dev: false - /sorcery@0.11.0: resolution: {integrity: sha512-J69LQ22xrQB1cIFJhPfgtLuI6BpWRiWu1Y3vSsIwK/eAScqJxd/+CJlUuHQRdX2C9NGFamq+KqNywGgaThwfHw==} hasBin: true @@ -5829,6 +6518,10 @@ packages: requiresBuild: true dev: true + /space-separated-tokens@2.0.2: + resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==} + dev: false + /spawn-error-forwarder@1.0.0: resolution: {integrity: sha512-gRjMgK5uFjbCvdibeGJuy3I5OYz6VLoVdsOJdA6wV0WlfQVLFueoqMxwwYD9RODdgb6oUIvlRlsyFSiQkMKu0g==} dev: true @@ -5926,6 +6619,13 @@ packages: safe-buffer: 5.2.1 dev: true + /stringify-entities@4.0.4: + resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==} + dependencies: + character-entities-html4: 2.1.0 + character-entities-legacy: 3.0.0 + dev: false + /strip-ansi@6.0.1: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} @@ -6504,6 +7204,10 @@ packages: resolution: {integrity: sha512-/y956gpUo9ZNCb99YjxG7OaslxZWHfCHAUUfshwqOXmxUIvqLjVO581BT+gM59+QV9tFe6/CGG53tsA1Y7RSdg==} dev: true + /trim-lines@3.0.1: + resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==} + dev: false + /trim-newlines@3.0.1: resolution: {integrity: sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==} engines: {node: '>=8'} @@ -6511,7 +7215,6 @@ packages: /trough@2.1.0: resolution: {integrity: sha512-AqTiAOLcj85xS7vQ8QkAV41hPDIJ71XJB4RCUrzo/1GM2CQwhkJGaf9Hgr7BOugMRpgGUrqRg/DrBDl4H40+8g==} - dev: true /ts-api-utils@1.0.3(typescript@5.3.3): resolution: {integrity: sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==} @@ -6694,7 +7397,6 @@ packages: is-plain-obj: 4.1.0 trough: 2.1.0 vfile: 6.0.1 - dev: true /unique-string@2.0.0: resolution: {integrity: sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==} @@ -6703,11 +7405,30 @@ packages: crypto-random-string: 2.0.0 dev: true + /unist-util-find-after@5.0.0: + resolution: {integrity: sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ==} + dependencies: + '@types/unist': 3.0.2 + unist-util-is: 6.0.0 + dev: false + /unist-util-is@6.0.0: resolution: {integrity: sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==} dependencies: '@types/unist': 3.0.2 - dev: true + + /unist-util-position@5.0.0: + resolution: {integrity: sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==} + dependencies: + '@types/unist': 3.0.2 + dev: false + + /unist-util-remove-position@5.0.0: + resolution: {integrity: sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q==} + dependencies: + '@types/unist': 3.0.2 + unist-util-visit: 5.0.0 + dev: false /unist-util-stringify-position@2.0.3: resolution: {integrity: sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g==} @@ -6719,14 +7440,12 @@ packages: resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==} dependencies: '@types/unist': 3.0.2 - dev: true /unist-util-visit-parents@6.0.1: resolution: {integrity: sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==} dependencies: '@types/unist': 3.0.2 unist-util-is: 6.0.0 - dev: true /unist-util-visit@5.0.0: resolution: {integrity: sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==} @@ -6734,7 +7453,6 @@ packages: '@types/unist': 3.0.2 unist-util-is: 6.0.0 unist-util-visit-parents: 6.0.1 - dev: true /universal-user-agent@6.0.1: resolution: {integrity: sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==} @@ -6792,6 +7510,13 @@ packages: engines: {node: '>= 0.10'} dev: true + /vfile-location@5.0.2: + resolution: {integrity: sha512-NXPYyxyBSH7zB5U6+3uDdd6Nybz6o6/od9rk8bp9H8GR3L+cm/fC0uUTbqBmUTnMCUDslAGBOIKNfvvb+gGlDg==} + dependencies: + '@types/unist': 3.0.2 + vfile: 6.0.1 + dev: false + /vfile-message@2.0.4: resolution: {integrity: sha512-DjssxRGkMvifUOJre00juHoP9DPWuzjxKuMDrhNbk2TdaYYBNMStsNhEOt3idrtI12VQYM/1+iM0KOzXi4pxwQ==} dependencies: @@ -6804,7 +7529,6 @@ packages: dependencies: '@types/unist': 3.0.2 unist-util-stringify-position: 4.0.0 - dev: true /vfile@6.0.1: resolution: {integrity: sha512-1bYqc7pt6NIADBJ98UiG0Bn/CHIVOoZ/IyEkqIruLg0mE1BKzkOXY2D6CSqQIcKqgadppE5lrxgWXJmXd7zZJw==} @@ -6812,7 +7536,6 @@ packages: '@types/unist': 3.0.2 unist-util-stringify-position: 4.0.0 vfile-message: 4.0.2 - dev: true /vite-plugin-dts@3.7.3(@types/node@18.16.3)(typescript@5.0.4)(vite@5.1.6): resolution: {integrity: sha512-26eTlBYdpjRLWCsTJebM8vkCieE+p9gP3raf+ecDnzzK5E3FG6VE1wcy55OkRpfWWVlVvKkYFe6uvRHYWx7Nog==} @@ -6915,6 +7638,10 @@ packages: defaults: 1.0.4 dev: true + /web-namespaces@2.0.1: + resolution: {integrity: sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==} + dev: false + /webidl-conversions@3.0.1: resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} dev: true @@ -7059,3 +7786,7 @@ packages: optionalDependencies: commander: 9.5.0 dev: true + + /zwitch@2.0.4: + resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} + dev: false From 7e4a38752352f46f0f45f98cd50acfd9330eca1a Mon Sep 17 00:00:00 2001 From: BearToCode Date: Thu, 11 Apr 2024 22:54:33 +0200 Subject: [PATCH 11/41] docs: update docs, add migration guide --- .vscode/settings.json | 1 + README.md | 24 +++-- docs/package.json | 2 +- docs/src/lib/components/code/Code.svelte | 8 +- .../src/lib/components/link/PluginLink.svelte | 12 +-- .../mobile-sidebar/MobileSidebar.svelte | 5 +- docs/src/lib/components/navbar/GitHub.svelte | 7 +- docs/src/lib/components/navbar/Search.svelte | 9 +- .../src/lib/components/sidebar/Sidebar.svelte | 44 ++++----- .../ui/command/command-input.svelte | 3 +- .../ui/dialog/dialog-content.svelte | 5 +- docs/src/lib/examples/DiscordExample.svelte | 6 +- docs/src/lib/examples/assets/PlusIcon.svelte | 3 + docs/src/lib/styles/markdown.scss | 4 + docs/src/pages/api/core.svelte.md | 18 ++++ docs/src/pages/api/extension.svelte.md | 50 +++++++++- docs/src/pages/api/utilities.svelte.md | 49 ++++++++++ docs/src/pages/editing-styles.svelte.md | 31 +++++- docs/src/pages/getting-started.svelte.md | 6 +- docs/src/pages/introduction.svelte.md | 38 ++++---- docs/src/pages/migration.svelte.md | 54 +++++++++++ docs/src/pages/plugins/anchor.svelte.md | 8 +- docs/src/pages/plugins/code.svelte.md | 64 +++---------- docs/src/pages/plugins/math.svelte.md | 24 ++--- docs/src/pages/plugins/tikz.svelte.md | 2 +- docs/src/routes/+layout.ts | 2 + packages/carta-md/README.md | 96 ++++++++++++++++--- packages/carta-md/src/lib/internal/carta.ts | 14 +-- .../carta-md/src/lib/internal/highlight.ts | 9 +- packages/plugin-anchor/src/lib/index.ts | 6 ++ packages/plugin-code/README.md | 26 ++--- pnpm-lock.yaml | 22 +++-- 32 files changed, 444 insertions(+), 208 deletions(-) create mode 100644 docs/src/lib/examples/assets/PlusIcon.svelte create mode 100644 docs/src/pages/migration.svelte.md diff --git a/.vscode/settings.json b/.vscode/settings.json index 1cee4ab..85e3f0d 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -7,6 +7,7 @@ "flexsearch", "Gemoji", "gruvbox", + "iconify", "Katex", "mdsvex", "oldschool", diff --git a/README.md b/README.md index 45d1f17..2c1ca4b 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@
Modern, lightweight, powerful Markdown Editor.

@@ -28,23 +28,29 @@ # Introduction -Carta is a **lightweight**, **fast** and **extensible** Svelte Markdown editor and viewer, based on [Marked](https://github.com/markedjs/marked). Check out the [examples](http://beartocode.github.io/carta/examples) to see it in action. -Differently from most editors, Carta includes neither ProseMirror nor CodeMirror, allowing for an extremely small bundle size and fast loading time. +> [!NOTE] +> Carta has recently been updated to `v4`, which features numerous major changes. +> +> Follow the [Migration Guide](http://beartocode.github.io/carta/migration) to update your project. + +Carta is a **lightweight**, **fast** and **extensible** Svelte Markdown editor and viewer. It is powered by [unified](https://github.com/unifiedjs/unified), [remark](https://github.com/remarkjs/remark) and [rehype](https://github.com/rehypejs/rehype). Check out the [examples](http://beartocode.github.io/carta/examples) to see it in action. +Differently from most editors, Carta does not include a Code Editor, but it is _just_ a textarea with syntax highlighting, shortcuts and more. ## Features -- ⌨️ Keyboard **shortcuts** (extensible); +- 🌈 Markdown syntax highlighting ([Shiki](https://shiki.style/)); - 🛠️ Toolbar (extensible); -- 🌈 Markdown syntax highlighting; +- ⌨️ Keyboard **shortcuts** (extensible); +- 📦 Supports **[+150 plugins](https://github.com/remarkjs/remark/blob/main/doc/plugins.md#list-of-plugins)** thanks to remark. - 🔀 Scroll sync; - ✅ Accessibility friendly; -- 💻 **SSR** compatible; +- 🖥️ **SSR** compatible; - ⚗️ **KaTeX** support (plugin); - 🔨 **Slash** commands (plugin); - 😄 **Emojis**, with included search (plugin); - ✏️ **TikZ** support (plugin); - 📂 **Attachment** support (plugin); -- ⚓ **Anchor** links in headings; +- ⚓ **Anchor** links in headings (plugin); - 🌈 Code blocks **syntax highlighting** (plugin). ## Packages @@ -74,6 +80,7 @@ Differently from most editors, Carta includes neither ProseMirror nor CodeMirror > [!WARNING] > Sanitization is not dealt with by Carta. You need to provide a `sanitizer` in the options. > Common sanitizers are [isomorphic-dompurify](https://www.npmjs.com/package/isomorphic-dompurify) (suggested) and [sanitize-html](https://www.npmjs.com/package/sanitize-html). +> Checkout the documentation for an example. ## Installation @@ -96,8 +103,6 @@ npm i @cartamd/plugin-name import { Carta, MarkdownEditor } from 'carta-md'; // Component default theme import 'carta-md/default.css'; - // Markdown input theme (Speed Highlight) - import 'carta-md/light.css'; const carta = new Carta({ // Remember to use a sanitizer to prevent XSS attacks @@ -112,6 +117,7 @@ npm i @cartamd/plugin-name /* Set your custom monospace font */ :global(.carta-font-code) { font-family: '...', monospace; + font-size: 1.1rem; } ``` diff --git a/docs/package.json b/docs/package.json index 1fd851b..7a24ff5 100644 --- a/docs/package.json +++ b/docs/package.json @@ -47,8 +47,8 @@ "clsx": "^2.0.0", "cmdk-sv": "^0.0.6", "flexsearch": "0.7.21", + "iconify-icon": "^2.0.0", "katex": "^0.16.10", - "radix-icons-svelte": "^1.2.1", "tailwind-merge": "^2.0.0" } } diff --git a/docs/src/lib/components/code/Code.svelte b/docs/src/lib/components/code/Code.svelte index f0b289b..8be7d1f 100644 --- a/docs/src/lib/components/code/Code.svelte +++ b/docs/src/lib/components/code/Code.svelte @@ -1,6 +1,4 @@ @@ -13,10 +11,10 @@ navigator.clipboard.writeText(elem.innerText); }} class=" - absolute right-4 top-[min(50%_,_32px)] -translate-y-1/2 transform - rounded p-2 hover:bg-neutral-800 hover:text-neutral-300 active:text-sky-300 + absolute right-4 top-[min(50%_,_32px)] aspect-square -translate-y-1/2 transform + rounded hover:bg-neutral-800 hover:text-neutral-300 active:text-sky-300 " > - +
diff --git a/docs/src/lib/components/link/PluginLink.svelte b/docs/src/lib/components/link/PluginLink.svelte index 90a884b..8318e91 100644 --- a/docs/src/lib/components/link/PluginLink.svelte +++ b/docs/src/lib/components/link/PluginLink.svelte @@ -1,18 +1,16 @@ - From 545864a20255be5a2dbdad89642cc6b90944e8be Mon Sep 17 00:00:00 2001 From: BearToCode Date: Sat, 13 Apr 2024 19:59:43 +0200 Subject: [PATCH 23/41] docs: fix grammar/style --- docs/src/pages/introduction.svelte.md | 2 +- docs/src/pages/migration.svelte.md | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/src/pages/introduction.svelte.md b/docs/src/pages/introduction.svelte.md index 6c706f8..12e0af9 100644 --- a/docs/src/pages/introduction.svelte.md +++ b/docs/src/pages/introduction.svelte.md @@ -13,7 +13,7 @@ Carta is a lightweight, fast and extensible Svelte Markdown editor and viewer, d ## Features -- 🌈 Markdown syntax highlighting ([shiki](https://shiki.style/)); +- 🌈 Markdown syntax highlighting ([Shiki](https://shiki.style/)); - 🛠️ Toolbar (extensible); - ⌨️ Keyboard **shortcuts** (extensible); - 📦 Supports **[+150 plugins](https://github.com/remarkjs/remark/blob/main/doc/plugins.md#list-of-plugins)** thanks to remark. diff --git a/docs/src/pages/migration.svelte.md b/docs/src/pages/migration.svelte.md index 744be26..1a2383c 100644 --- a/docs/src/pages/migration.svelte.md +++ b/docs/src/pages/migration.svelte.md @@ -21,7 +21,7 @@ Make sure to remove previous themes imports, as Shiki uses JS based ones. import 'carta-md/light.css'; // 👈 To be removed! ``` -And also update the default theme. SHJ based selectors should be removed: +And also update the default theme. Previous based selectors should be removed: ```css [class*='shj-lang-'] { @@ -32,7 +32,7 @@ And also update the default theme. SHJ based selectors should be removed: ## Removed verbose prefixes -Many exports have been renamed to make them less verbose, here are them: +Many exports have been renamed to make them less verbose: - `CartaEditor` -> `MarkdownEditor` (old one still supported); - `CartaRenderer` -> `Markdown` (old one still supported); @@ -49,7 +49,7 @@ Many exports have been renamed to make them less verbose, here are them: - `CartaRenderer` -> `Renderer`; - `CartaLabels` -> `Labels`; -## Minor Changes +# Minor Changes - If you don't use a sanitizer, you need to explicitly set it to `false`; - Removed deprecated option `cartaRef` and `shjRef` for extensions; From 7ad874e6aae2862e53586ecb91c86ed14e24ffc0 Mon Sep 17 00:00:00 2001 From: BearToCode Date: Sun, 14 Apr 2024 18:08:33 +0200 Subject: [PATCH 24/41] fix(plugin-code): module not found error --- packages/plugin-code/src/index.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/plugin-code/src/index.ts b/packages/plugin-code/src/index.ts index 3bcc501..5b47439 100644 --- a/packages/plugin-code/src/index.ts +++ b/packages/plugin-code/src/index.ts @@ -1,5 +1,5 @@ -import { DualTheme, Theme, isSingleTheme, type Plugin } from 'carta-md'; -import { type RehypeShikiOptions } from '@shikijs/rehype'; +import type { DualTheme, Theme, Plugin } from 'carta-md'; +import type { RehypeShikiOptions } from '@shikijs/rehype'; import rehypeShikiFromHighlighter from '@shikijs/rehype/core'; export type CodeExtensionOptions = Omit & { @@ -17,6 +17,7 @@ export const code = (options?: CodeExtensionOptions): Plugin => { type: 'rehype', async transform({ processor, carta }) { let theme = options?.theme; + const { isSingleTheme } = await import('carta-md'); const highlighter = await carta.highlighter(); if (!theme) { theme = highlighter.theme; // Use the theme specified in the highlighter From 54358b649b49699ef85c779745ad1b5b78e32734 Mon Sep 17 00:00:00 2001 From: BearToCode Date: Sun, 14 Apr 2024 18:24:18 +0200 Subject: [PATCH 25/41] fix(plugin-code): do not import `isSingleTheme` for main package fix #50 --- packages/plugin-code/src/index.ts | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/packages/plugin-code/src/index.ts b/packages/plugin-code/src/index.ts index 5b47439..48a8d6e 100644 --- a/packages/plugin-code/src/index.ts +++ b/packages/plugin-code/src/index.ts @@ -6,6 +6,23 @@ export type CodeExtensionOptions = Omit theme?: Theme | DualTheme; }; +// FIXME: find a better solution then copy-pasting these functions in next version. +// However, when importing from carta-md, this causes a MODULE_NOT_FOUND error +// for some reason. +/** + * Checks if a theme is a dual theme. + * @param theme The theme to check. + * @returns Whether the theme is a dual theme. + */ +export const isDualTheme = (theme: Theme | DualTheme): theme is DualTheme => + typeof theme == 'object' && 'light' in theme && 'dark' in theme; +/** + * Checks if a theme is a single theme. + * @param theme The theme to check. + * @returns Whether the theme is a single theme. + */ +export const isSingleTheme = (theme: Theme | DualTheme): theme is Theme => !isDualTheme(theme); + /** * Carta code highlighting plugin. Themes available on [GitHub](https://github.com/speed-highlight/core/tree/main/dist/themes). */ @@ -17,7 +34,7 @@ export const code = (options?: CodeExtensionOptions): Plugin => { type: 'rehype', async transform({ processor, carta }) { let theme = options?.theme; - const { isSingleTheme } = await import('carta-md'); + const highlighter = await carta.highlighter(); if (!theme) { theme = highlighter.theme; // Use the theme specified in the highlighter From dfc8812123974a4e672e3e711b9f08e5e29d25cf Mon Sep 17 00:00:00 2001 From: BearToCode Date: Sun, 14 Apr 2024 18:37:48 +0200 Subject: [PATCH 26/41] fix(plugin-tikz): prevent crash when className property is not set --- packages/plugin-tikz/src/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/plugin-tikz/src/index.ts b/packages/plugin-tikz/src/index.ts index f46161b..895eb62 100644 --- a/packages/plugin-tikz/src/index.ts +++ b/packages/plugin-tikz/src/index.ts @@ -95,6 +95,7 @@ const tikzTransformer: UnifiedPlugin< if (node.type !== 'element') return; const element = node as hast.Element; if (element.tagName !== 'code') return; + if (!element.properties['className']) return; if (!(element.properties['className'] as string[]).includes('language-tikz')) return; // Element is a TikZ code block From 482fd4b8af314ec61afe18882a0fbc36549a4824 Mon Sep 17 00:00:00 2001 From: BearToCode Date: Mon, 15 Apr 2024 18:16:43 +0200 Subject: [PATCH 27/41] fix(plugin-tikz): remove wrapping pre --- packages/plugin-tikz/src/index.ts | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/plugin-tikz/src/index.ts b/packages/plugin-tikz/src/index.ts index 895eb62..8ef05de 100644 --- a/packages/plugin-tikz/src/index.ts +++ b/packages/plugin-tikz/src/index.ts @@ -86,14 +86,18 @@ const tikzTransformer: UnifiedPlugin< hast.Root > = ({ carta, options }) => { return async function (tree) { - visit(tree, (node, index, parent) => { + visit(tree, (pre, index, parent) => { if (typeof document === 'undefined') { // Cannot run outside the browser return; } - if (node.type !== 'element') return; - const element = node as hast.Element; + if (pre.type !== 'element') return; + const preElement = pre as hast.Element; + if (preElement.tagName !== 'pre') return; + const element = pre.children.at(0) as hast.Element | undefined; + if (!element) return; + if (element.tagName !== 'code') return; if (!element.properties['className']) return; if (!(element.properties['className'] as string[]).includes('language-tikz')) return; @@ -130,6 +134,7 @@ const tikzTransformer: UnifiedPlugin< } const hastNode = fromDom(container) as hast.Element; + parent?.children.splice(index!, 1, hastNode); return [SKIP, index!]; From 7261d295e2bb48974b9048b98d5b0fa057d0456c Mon Sep 17 00:00:00 2001 From: BearToCode Date: Thu, 18 Apr 2024 12:49:11 +0200 Subject: [PATCH 28/41] docs: fix editor code having padding --- docs/src/lib/styles/markdown.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/src/lib/styles/markdown.scss b/docs/src/lib/styles/markdown.scss index cef9e64..6cefde8 100644 --- a/docs/src/lib/styles/markdown.scss +++ b/docs/src/lib/styles/markdown.scss @@ -49,5 +49,6 @@ .carta-editor code { font-family: 'Fira Code', monospace; background: transparent; + padding: 0; } } From dddaad1f1bbea4b4be427b1d4f879d1d43edbe90 Mon Sep 17 00:00:00 2001 From: BearToCode Date: Sat, 20 Apr 2024 19:46:00 +0200 Subject: [PATCH 29/41] fix(plugin-anchor): wrong class in default stylesheet --- packages/plugin-anchor/src/lib/default.css | 36 +++++++++++----------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/packages/plugin-anchor/src/lib/default.css b/packages/plugin-anchor/src/lib/default.css index afbed18..1d18753 100644 --- a/packages/plugin-anchor/src/lib/default.css +++ b/packages/plugin-anchor/src/lib/default.css @@ -1,18 +1,18 @@ -.carta-renderer h1, -.carta-renderer h2, -.carta-renderer h3, -.carta-renderer h4, -.carta-renderer h5, -.carta-renderer h6 { +.carta-viewer h1, +.carta-viewer h2, +.carta-viewer h3, +.carta-viewer h4, +.carta-viewer h5, +.carta-viewer h6 { position: relative; } -.carta-renderer h1 .icon.icon-link, -.carta-renderer h2 .icon.icon-link, -.carta-renderer h3 .icon.icon-link, -.carta-renderer h4 .icon.icon-link, -.carta-renderer h5 .icon.icon-link, -.carta-renderer h6 .icon.icon-link { +.carta-viewer h1 .icon.icon-link, +.carta-viewer h2 .icon.icon-link, +.carta-viewer h3 .icon.icon-link, +.carta-viewer h4 .icon.icon-link, +.carta-viewer h5 .icon.icon-link, +.carta-viewer h6 .icon.icon-link { opacity: 0; content: url('./link.svg'); position: absolute; @@ -22,11 +22,11 @@ transform: translateY(-50%); } -.carta-renderer h1:hover .icon-link, -.carta-renderer h2:hover .icon-link, -.carta-renderer h3:hover .icon-link, -.carta-renderer h4:hover .icon-link, -.carta-renderer h5:hover .icon-link, -.carta-renderer h6:hover .icon-link { +.carta-viewer h1:hover .icon-link, +.carta-viewer h2:hover .icon-link, +.carta-viewer h3:hover .icon-link, +.carta-viewer h4:hover .icon-link, +.carta-viewer h5:hover .icon-link, +.carta-viewer h6:hover .icon-link { opacity: 1; } From a086ece08804dc842d9a94b0f2bc7109d2b9b428 Mon Sep 17 00:00:00 2001 From: BearToCode Date: Sat, 20 Apr 2024 20:05:27 +0200 Subject: [PATCH 30/41] docs: update old plugin code readme --- packages/plugin-code/README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/plugin-code/README.md b/packages/plugin-code/README.md index 7eab23b..1f0dc18 100644 --- a/packages/plugin-code/README.md +++ b/packages/plugin-code/README.md @@ -1,13 +1,11 @@ # Carta Code Plugin -This plugin adds support for code blocks **syntax highlighting**. Install it using: +This plugin adds support for code blocks **syntax highlighting**. It uses the same highlighter from the core package(Shiki). ``` npm i @cartamd/plugin-code ``` -This is done using [Speed-highlight JS](https://github.com/speed-highlight/core), which supports dynamic imports. This way, languages definitions are only imported at the moment of need. - ## Setup ### Styles From bafc86d8d306a2de3bd571db629abdfaa4949c9d Mon Sep 17 00:00:00 2001 From: BearToCode Date: Sun, 28 Apr 2024 15:46:51 +0200 Subject: [PATCH 31/41] fix: handle caret endings in Markdown component fix: #56 --- .../carta-md/src/lib/internal/components/Input.svelte | 8 ++------ packages/carta-md/src/lib/internal/highlight.ts | 2 ++ 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/packages/carta-md/src/lib/internal/components/Input.svelte b/packages/carta-md/src/lib/internal/components/Input.svelte index c3fe8b6..3874591 100644 --- a/packages/carta-md/src/lib/internal/components/Input.svelte +++ b/packages/carta-md/src/lib/internal/components/Input.svelte @@ -63,18 +63,14 @@ } }; - const normalize = (text: string) => { - return text.replaceAll('\r\n', '\n'); - }; - const highlightNestedLanguages = debounce(async (text: string) => { const highlighter = await carta.highlighter(); const { updated } = await loadNestedLanguages(highlighter, text); if (updated) highlight(text); }, 300); - $: highlight(normalize(value)).then(resize); - $: highlightNestedLanguages(normalize(value)); + $: highlight(value).then(resize); + $: highlightNestedLanguages(value); onMount(() => { mounted = true; diff --git a/packages/carta-md/src/lib/internal/highlight.ts b/packages/carta-md/src/lib/internal/highlight.ts index ed2df86..16cfddf 100644 --- a/packages/carta-md/src/lib/internal/highlight.ts +++ b/packages/carta-md/src/lib/internal/highlight.ts @@ -249,6 +249,8 @@ const findNestedLanguages = (text: string) => { * @returns Whether the highlighter was updated with new languages. */ export const loadNestedLanguages = async (highlighter: Highlighter, text: string) => { + text = text.replaceAll('\r\n', '\n'); // Normalize line endings + const languages = findNestedLanguages(text); const loadedLanguages = highlighter.getLoadedLanguages(); let updated = false; From a44b8e971dd0e57f097f79dabf77870f96bdcc24 Mon Sep 17 00:00:00 2001 From: BearToCode Date: Wed, 1 May 2024 16:30:13 +0200 Subject: [PATCH 32/41] docs: add dark mode chapter --- docs/src/pages/editing-styles.svelte.md | 32 +++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/docs/src/pages/editing-styles.svelte.md b/docs/src/pages/editing-styles.svelte.md index e54df5a..a695761 100644 --- a/docs/src/pages/editing-styles.svelte.md +++ b/docs/src/pages/editing-styles.svelte.md @@ -43,11 +43,35 @@ While the core styles are embedded in the Svelte components, the others can be s ### Using multiple themes -By using the `theme` property in the editor you can differentiate the themes of multiple editors. +By using the `theme` property in `` you can differentiate the themes of multiple editors. -## Changing Markdown color theme +## Dark mode -Carta uses [Shiki](https://shiki.matsu.io/) for syntax highlighting. Two default themes are included in the core package, which are as a [dual theme](https://shiki.matsu.io/guide/dual-themes) used for light and dark mode. +When using dark mode, there are two different themes that have to be changed: the editor theme and the one used for syntax highlighting: + +```css +/* Editor dark mode */ +/* Only if you are using the default theme */ +html.dark .carta-theme__default { + --border-color: var(--border-color-dark); + --selection-color: var(--selection-color-dark); + --focus-outline: var(--focus-outline-dark); + --hover-color: var(--hover-color-dark); + --caret-color: var(--caret-color-dark); + --text-color: var(--text-color-dark); +} + +/* Code dark mode */ +/* Only if you didn't specify a custom code theme */ +html.dark .shiki, +html.dark .shiki span { + color: var(--shiki-dark) !important; +} +``` + +## Changing Markdown input color theme + +Carta uses [Shiki](https://shiki.matsu.io/) for syntax highlighting. Two default themes are included in the core package, which are set as a [dual theme](https://shiki.matsu.io/guide/dual-themes) to support light and dark mode. If you plan to use a custom one with light/dark modes, make sure to use a dual theme as well. You can change theme in the options: @@ -62,7 +86,7 @@ const carta = new Carta({ -If you use a [custom theme](https://shiki.matsu.io/guide/load-theme)(or also a custom language), you need to specify it, so that it gets loaded into the highlighter: +If you use a [custom theme](https://shiki.matsu.io/guide/load-theme)(or a custom language), you need to provide it inside the options, so that it gets loaded into the highlighter: From cc79b252881236fa6e7e2aee25c9cfc1580a171c Mon Sep 17 00:00:00 2001 From: BearToCode Date: Wed, 1 May 2024 16:35:47 +0200 Subject: [PATCH 33/41] docs: add missing copy button --- docs/src/pages/editing-styles.svelte.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/src/pages/editing-styles.svelte.md b/docs/src/pages/editing-styles.svelte.md index a695761..81736ed 100644 --- a/docs/src/pages/editing-styles.svelte.md +++ b/docs/src/pages/editing-styles.svelte.md @@ -49,6 +49,8 @@ By using the `theme` property in `` you can differentiate the th When using dark mode, there are two different themes that have to be changed: the editor theme and the one used for syntax highlighting: + + ```css /* Editor dark mode */ /* Only if you are using the default theme */ @@ -69,6 +71,8 @@ html.dark .shiki span { } ``` + + ## Changing Markdown input color theme Carta uses [Shiki](https://shiki.matsu.io/) for syntax highlighting. Two default themes are included in the core package, which are set as a [dual theme](https://shiki.matsu.io/guide/dual-themes) to support light and dark mode. If you plan to use a custom one with light/dark modes, make sure to use a dual theme as well. From 34d4f400e6675914daf87651b60a6df1ebe996a4 Mon Sep 17 00:00:00 2001 From: BearToCode Date: Wed, 1 May 2024 18:15:42 +0200 Subject: [PATCH 34/41] docs: fix wrong name for Plugins --- docs/src/pages/migration.svelte.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/pages/migration.svelte.md b/docs/src/pages/migration.svelte.md index 1a2383c..1241d61 100644 --- a/docs/src/pages/migration.svelte.md +++ b/docs/src/pages/migration.svelte.md @@ -38,7 +38,7 @@ Many exports have been renamed to make them less verbose: - `CartaRenderer` -> `Markdown` (old one still supported); - `CartaEvent` -> `Event`; - `CartaEventType` -> `EventType`; -- `CartaExtension` -> `Extension`; +- `CartaExtension` -> `Plugin`; - `CartaExtensionComponent` -> `ExtensionComponent`; - `CartaOptions` -> `Options`; - `CartaHistory` -> `TextAreaHistory`; From eb114a73114324681c933fada6e6ee0763073848 Mon Sep 17 00:00:00 2001 From: BearToCode Date: Wed, 1 May 2024 18:21:40 +0200 Subject: [PATCH 35/41] docs: small fix in style --- docs/src/pages/migration.svelte.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/pages/migration.svelte.md b/docs/src/pages/migration.svelte.md index 1241d61..72d25dc 100644 --- a/docs/src/pages/migration.svelte.md +++ b/docs/src/pages/migration.svelte.md @@ -24,8 +24,8 @@ import 'carta-md/light.css'; // 👈 To be removed! And also update the default theme. Previous based selectors should be removed: ```css +/* 👇 To be removed! */ [class*='shj-lang-'] { - /* 👈 To be removed! */ /* ... */ } ``` From 0ff9e5b124a70ca2f3d76570a77aaeae1892c6d6 Mon Sep 17 00:00:00 2001 From: BearToCode Date: Thu, 2 May 2024 11:26:12 +0200 Subject: [PATCH 36/41] docs: add guide on using Svelte components --- .../src/lib/components/sidebar/Sidebar.svelte | 6 + docs/src/lib/styles/markdown.scss | 6 + docs/src/pages/using-components.svelte.md | 217 ++++++++++++++++++ 3 files changed, 229 insertions(+) create mode 100644 docs/src/pages/using-components.svelte.md diff --git a/docs/src/lib/components/sidebar/Sidebar.svelte b/docs/src/lib/components/sidebar/Sidebar.svelte index b02930c..cb82c46 100644 --- a/docs/src/lib/components/sidebar/Sidebar.svelte +++ b/docs/src/lib/components/sidebar/Sidebar.svelte @@ -45,6 +45,12 @@ Community Plugins + + + + Using Components + +

Plugins

diff --git a/docs/src/lib/styles/markdown.scss b/docs/src/lib/styles/markdown.scss index 6cefde8..4f87a64 100644 --- a/docs/src/lib/styles/markdown.scss +++ b/docs/src/lib/styles/markdown.scss @@ -46,6 +46,12 @@ @apply rounded bg-neutral-800 px-1 text-neutral-50; } + p, h1, h2, h3 { + code { + @apply px-1; + } + } + .carta-editor code { font-family: 'Fira Code', monospace; background: transparent; diff --git a/docs/src/pages/using-components.svelte.md b/docs/src/pages/using-components.svelte.md new file mode 100644 index 0000000..185196b --- /dev/null +++ b/docs/src/pages/using-components.svelte.md @@ -0,0 +1,217 @@ +--- +title: Using Svelte Components +section: Overview +--- + + + +Svelte components can be embedded into the rendered HTML to make certain elements interactive. However, they require a bit more work, as Remark is configured to only render static HTML. To get around this, the idea is to do the following: + +1. Create a Unified plugin to isolate the targeted element; +2. Replace all the elements with the component, after every render. + +## Example + +Let's say we want to replace all hashtags, such as `#something`, with a custom component. Here is as example of how that could be achieved. + +### Parsing the hashtags + +First things first: we need to tell the parser that we want to parse hashtags as custom elements. To do this, we it's useful to first install the following packages: + + + +```shell +npm i unist-util-visit +# Types +npm i -D unified hast +``` + + + +Let's create a Unified plugin. The basic structure of a plugin is the following: + + + +```ts +import type { Plugin as UnifiedPlugin } from 'unified' +import { SKIP, visit } from 'unist-util-visit' + +const unifiedPlugin: UnifiedPlugin<[], hast.Root> = () => { + return function (tree) { + // Visit every node in the syntax tree + visit(tree, (node, index, parent) => { + // Do something with the node + } + } +} +``` + + + +We now want to parse text nodes, so that words such as `#pizza` and `#123` are separated from the rest. This is a possible implementation: + + + +```ts +const unifiedPlugin: UnifiedPlugin<[], hast.Root> = () => { + return function (tree) { + visit(tree, (node, index, parent) => { + // Skip code blocks and their children + if (node.type === 'element' && node.tagName === 'pre') return [SKIP]; + // Skip non-text nodes + if (node.type !== 'text') return; + const text = node as hast.Text; + + // Parse the text node and replace hashtags with spans + const regex = /#(\w+)/g; + const children: (hast.Element | hast.Text)[] = []; + let lastIndex = 0; + let match; + while ((match = regex.exec(text.value))) { + const before = text.value.slice(lastIndex, match.index); + if (before) { + children.push({ type: 'text', value: before }); + } + children.push({ + type: 'element', + tagName: 'span', + properties: { type: 'hashtag', value: match[1] }, + children: [{ type: 'text', value: match[0] }] + }); + lastIndex = regex.lastIndex; + } + if (lastIndex < text.value.length) { + children.push({ type: 'text', value: text.value.slice(lastIndex) }); + } + + // Replace the text node with all the children + parent!.children.splice(index!, 1, ...children); + + // Skip the children + return [SKIP, index! + children.length]; + }); + }; +}; +``` + + + +If you want a more in-depth guide on writing Unified plugins, you can check out the official [documentation](https://unifiedjs.com/learn/guide/create-a-plugin/). + +Notice that hashtags are now replaced with the following: + +```html + #pizza +``` + +### Configuring the transformer + +Unified plugins need to be wrapped inside a `UnifiedTransformer` type, to be able to be used in Carta. + + + +```ts +import type { UnifiedTransformer } from 'carta-md'; + +const hashtagTransformer: UnifiedTransformer<'sync'> = { + execution: 'sync', // Sync, since the plugin is synchronous + type: 'rehype', // Rehype, since it operates on HTML + transform({ processor }) { + processor.use(unifiedPlugin); + } +}; +``` + + + +### Mounting the components + +We now want to replace the generated hashtag placeholders with the following element: + + + +```svelte + + + + +``` + + + +To do that, we create a listener that: + +1. Finds all the previous placeholders; +2. Mounts the component next to them; +3. Removes the placeholders. + + + +```ts +import type { Listener } from 'carta-md'; +import Hashtag from './Hashtag.svelte'; + +const convertHashtags: Listener<'carta-render'> = [ + 'carta-render', + function onRender({ detail: { carta } }) { + const rendererContainer = carta.renderer?.container; + if (!rendererContainer) return; + + // Find all hashtag spans and replace them with Svelte components + const hashtagSpans = rendererContainer.querySelectorAll('span[type="hashtag"]'); + for (const span of hashtagSpans) { + const hashtag = span.getAttribute('value') ?? ''; + + new Hashtag({ + target: span.parentElement!, + anchor: span, + props: { value: hashtag } + }); + + span.remove(); + } + } +]; +``` + + + +### Using the plugin + +Let's now create a Plugin with the transformer and the listener: + + + +```ts +import type { Plugin } from 'carta-md'; + +export const hashtag = (): Plugin => ({ + transformers: [hashtagTransformer], + listeners: [convertHashtags] +}); +``` + + + +We can now use the plugin with the following: + +```ts +import { Carta } from 'carta-md'; + +const carta = new Carta({ + // ... + extensions: [hashtag()] +}); +``` + +You can find the example source code [here](https://github.com/BearToCode/svelte-in-carta-example). From 8e5803a1c4938ed5517c18f753983b5adb321af0 Mon Sep 17 00:00:00 2001 From: BearToCode Date: Thu, 2 May 2024 11:30:35 +0200 Subject: [PATCH 37/41] docs: fix style check issue --- docs/src/lib/styles/markdown.scss | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/src/lib/styles/markdown.scss b/docs/src/lib/styles/markdown.scss index 4f87a64..61eb539 100644 --- a/docs/src/lib/styles/markdown.scss +++ b/docs/src/lib/styles/markdown.scss @@ -46,7 +46,10 @@ @apply rounded bg-neutral-800 px-1 text-neutral-50; } - p, h1, h2, h3 { + p, + h1, + h2, + h3 { code { @apply px-1; } From 486a8857044b44bf36095f003c1422552cd1b8d2 Mon Sep 17 00:00:00 2001 From: BearToCode Date: Thu, 2 May 2024 17:11:26 +0200 Subject: [PATCH 38/41] docs: specify to load the language into the highlighter --- packages/plugin-code/README.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/plugin-code/README.md b/packages/plugin-code/README.md index 1f0dc18..cbb5c68 100644 --- a/packages/plugin-code/README.md +++ b/packages/plugin-code/README.md @@ -18,7 +18,7 @@ import '@cartamd/plugin-code/default.css'; ### Using the default highlighter -Carta comes with a default highlighter that matches the one used to highlight markdown in the editor and is used by default (Shiki). If you want to use a theme different from the one used to highlight Markdown, you can specify it in the options. +Carta comes with a default highlighter that matches the one used to highlight markdown in the editor and is used by default (Shiki). If you want to use a theme different from the one used to highlight Markdown, you can specify it in the options. Remember to also have it loaded into the highlighter, by specifying it in `shikiOptions`. ```ts const carta = new Carta({ @@ -27,7 +27,10 @@ const carta = new Carta({ code({ theme: 'ayu-light' }) - ] + ], + shikiOptions: { + themes: ['ayu-light'] + } }); ``` From 3fd18a6796989a0d85a11e78e28ec10fcbcb995b Mon Sep 17 00:00:00 2001 From: BearToCode Date: Thu, 2 May 2024 17:26:17 +0200 Subject: [PATCH 39/41] fix: update shiki, fix latex highlighting issues --- packages/carta-md/package.json | 2 +- packages/plugin-code/package.json | 2 +- pnpm-lock.yaml | 14 ++++++++++++-- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/packages/carta-md/package.json b/packages/carta-md/package.json index e1eeb05..bc074ef 100644 --- a/packages/carta-md/package.json +++ b/packages/carta-md/package.json @@ -39,7 +39,7 @@ "remark-gfm": "^4.0.0", "remark-parse": "^11.0.0", "remark-rehype": "^11.1.0", - "shiki": "^1.3.0", + "shiki": "^1.4.0", "unified": "^11.0.4" }, "peerDependencies": { diff --git a/packages/plugin-code/package.json b/packages/plugin-code/package.json index e57937b..98d68df 100644 --- a/packages/plugin-code/package.json +++ b/packages/plugin-code/package.json @@ -16,7 +16,7 @@ "build": "tsc && tscp" }, "devDependencies": { - "@shikijs/rehype": "^1.3.0", + "@shikijs/rehype": "^1.4.0", "@types/node": "^18.16.3", "carta-md": "workspace:*", "typescript": "^5.0.4", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f2eb6c4..376b0ad 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -172,8 +172,8 @@ importers: specifier: ^11.1.0 version: 11.1.0 shiki: - specifier: ^1.3.0 - version: 1.3.0 + specifier: ^1.4.0 + version: 1.4.0 svelte: specifier: ^3.54.0 || ^4.0.0 version: 4.2.2 @@ -1426,6 +1426,10 @@ packages: resolution: {integrity: sha512-7fedsBfuILDTBmrYZNFI8B6ATTxhQAasUHllHmjvSZPnoq4bULWoTpHwmuQvZ8Aq03/tAa2IGo6RXqWtHdWaCA==} dev: false + /@shikijs/core@1.4.0: + resolution: {integrity: sha512-CxpKLntAi64h3j+TwWqVIQObPTED0FyXLHTTh3MKXtqiQNn2JGcMQQ362LftDbc9kYbDtrksNMNoVmVXzKFYUQ==} + dev: false + /@shikijs/rehype@1.3.0: resolution: {integrity: sha512-CknEidx0ZTg3TeYAPU4ah8cr31a16neBbMyQ5kwAVdkloCe65uhQp+C/FEFs8NRir4eU5XCDA/+w2v5wnN6zgQ==} dependencies: @@ -6441,6 +6445,12 @@ packages: '@shikijs/core': 1.3.0 dev: false + /shiki@1.4.0: + resolution: {integrity: sha512-5WIn0OL8PWm7JhnTwRWXniy6eEDY234mRrERVlFa646V2ErQqwIFd2UML7e0Pq9eqSKLoMa3Ke+xbsF+DAuy+Q==} + dependencies: + '@shikijs/core': 1.4.0 + dev: false + /signal-exit@3.0.7: resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} dev: true From a303834127118e78a0e4d81dbe6930665f81c141 Mon Sep 17 00:00:00 2001 From: BearToCode Date: Thu, 2 May 2024 19:26:54 +0200 Subject: [PATCH 40/41] build: fix shiki version difference --- packages/plugin-code/package.json | 2 +- pnpm-lock.yaml | 28 +++++++++------------------- 2 files changed, 10 insertions(+), 20 deletions(-) diff --git a/packages/plugin-code/package.json b/packages/plugin-code/package.json index 98d68df..0da3535 100644 --- a/packages/plugin-code/package.json +++ b/packages/plugin-code/package.json @@ -30,7 +30,7 @@ ], "version": "4.0.0", "dependencies": { - "@shikijs/rehype": "^1.3.0", + "@shikijs/rehype": "^1.4.0", "unified": "^11.0.4" }, "keywords": [ diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 376b0ad..1968455 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -297,8 +297,8 @@ importers: packages/plugin-code: dependencies: '@shikijs/rehype': - specifier: ^1.3.0 - version: 1.3.0 + specifier: ^1.4.0 + version: 1.4.0 unified: specifier: ^11.0.4 version: 11.0.4 @@ -1422,29 +1422,25 @@ packages: - supports-color dev: true - /@shikijs/core@1.3.0: - resolution: {integrity: sha512-7fedsBfuILDTBmrYZNFI8B6ATTxhQAasUHllHmjvSZPnoq4bULWoTpHwmuQvZ8Aq03/tAa2IGo6RXqWtHdWaCA==} - dev: false - /@shikijs/core@1.4.0: resolution: {integrity: sha512-CxpKLntAi64h3j+TwWqVIQObPTED0FyXLHTTh3MKXtqiQNn2JGcMQQ362LftDbc9kYbDtrksNMNoVmVXzKFYUQ==} dev: false - /@shikijs/rehype@1.3.0: - resolution: {integrity: sha512-CknEidx0ZTg3TeYAPU4ah8cr31a16neBbMyQ5kwAVdkloCe65uhQp+C/FEFs8NRir4eU5XCDA/+w2v5wnN6zgQ==} + /@shikijs/rehype@1.4.0: + resolution: {integrity: sha512-Ba6QHYx+EIEvmqyNy/B49KAz3rXsTfAqYRY3KTZjPWonytokGOiJ1q/FV9l13D/ad6Qv+eWKhkAz6ITxx6ziFA==} dependencies: - '@shikijs/transformers': 1.3.0 + '@shikijs/transformers': 1.4.0 '@types/hast': 3.0.4 hast-util-to-string: 3.0.0 - shiki: 1.3.0 + shiki: 1.4.0 unified: 11.0.4 unist-util-visit: 5.0.0 dev: false - /@shikijs/transformers@1.3.0: - resolution: {integrity: sha512-3mlpg2I9CjhjE96dEWQOGeCWoPcyTov3s4aAsHmgvnTHa8MBknEnCQy8/xivJPSpD+olqOqIEoHnLfbNJK29AA==} + /@shikijs/transformers@1.4.0: + resolution: {integrity: sha512-kzvlWmWYYSeaLKRce/kgmFFORUtBtFahfXRKndor0b60ocYiXufBQM6d6w1PlMuUkdk55aor9xLvy9wy7hTEJg==} dependencies: - shiki: 1.3.0 + shiki: 1.4.0 dev: false /@sveltejs/adapter-auto@3.1.1(@sveltejs/kit@2.5.4): @@ -6439,12 +6435,6 @@ packages: engines: {node: '>=8'} dev: true - /shiki@1.3.0: - resolution: {integrity: sha512-9aNdQy/etMXctnPzsje1h1XIGm9YfRcSksKOGqZWXA/qP9G18/8fpz5Bjpma8bOgz3tqIpjERAd6/lLjFyzoww==} - dependencies: - '@shikijs/core': 1.3.0 - dev: false - /shiki@1.4.0: resolution: {integrity: sha512-5WIn0OL8PWm7JhnTwRWXniy6eEDY234mRrERVlFa646V2ErQqwIFd2UML7e0Pq9eqSKLoMa3Ke+xbsF+DAuy+Q==} dependencies: From 21775454544fdc4294524eac6e266477ce6c206b Mon Sep 17 00:00:00 2001 From: BearToCode Date: Thu, 2 May 2024 19:28:12 +0200 Subject: [PATCH 41/41] docs: fix grammar --- docs/src/pages/using-components.svelte.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/src/pages/using-components.svelte.md b/docs/src/pages/using-components.svelte.md index 185196b..f301c51 100644 --- a/docs/src/pages/using-components.svelte.md +++ b/docs/src/pages/using-components.svelte.md @@ -18,7 +18,7 @@ Let's say we want to replace all hashtags, such as `#something`, with a custom c ### Parsing the hashtags -First things first: we need to tell the parser that we want to parse hashtags as custom elements. To do this, we it's useful to first install the following packages: +First things first: we need to tell the parser that we want to parse hashtags as custom elements. To do this, it's useful to first install the following packages: @@ -103,7 +103,7 @@ If you want a more in-depth guide on writing Unified plugins, you can check out Notice that hashtags are now replaced with the following: ```html - #pizza + #pizza ``` ### Configuring the transformer