diff --git a/.github/workflows/code-quality.yml b/.github/workflows/code-quality.yml index 842d40c..c9c1775 100644 --- a/.github/workflows/code-quality.yml +++ b/.github/workflows/code-quality.yml @@ -13,7 +13,7 @@ jobs: - uses: actions/setup-node@v3 - uses: pnpm/action-setup@v2 with: - version: 8 + version: 6 - name: Install dependendencies run: pnpm i diff --git a/.github/workflows/gh-pages.yml b/.github/workflows/gh-pages.yml index 731c3a1..7425634 100644 --- a/.github/workflows/gh-pages.yml +++ b/.github/workflows/gh-pages.yml @@ -17,7 +17,7 @@ jobs: - uses: actions/setup-node@v3 - uses: pnpm/action-setup@v2 with: - version: 8 + version: 6 - name: Install dependencies run: pnpm i @@ -33,4 +33,4 @@ jobs: uses: peaceiris/actions-gh-pages@v3 with: github_token: ${{ secrets.GITHUB_TOKEN }} - publish_dir: ./docs/build + publish_dir: ./demo/build diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 84a2e6e..be810b1 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -16,7 +16,7 @@ jobs: - uses: actions/setup-node@v3 - uses: pnpm/action-setup@v2 with: - version: 8 + version: 6 - name: Install dependendencies run: pnpm i @@ -45,7 +45,7 @@ jobs: - uses: actions/setup-node@v3 - uses: pnpm/action-setup@v2 with: - version: 8 + version: 6 - name: Install dependendencies run: pnpm i @@ -53,6 +53,9 @@ jobs: - name: Build all packages run: pnpm build + - name: Verify the integrity of provenance attestations and registry signatures for installed dependencies + run: npm audit signatures + - name: Release run: npm run publish env: diff --git a/.vscode/settings.json b/.vscode/settings.json index 85e3f0d..7fd34f4 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -5,15 +5,11 @@ "coldark", "dompurify", "flexsearch", - "Gemoji", "gruvbox", - "iconify", "Katex", "mdsvex", "oldschool", "rehype", - "shiki", - "shikijs", "tikz", "tikzjax", "typeof" @@ -21,6 +17,5 @@ "typescript.tsdk": "node_modules\\typescript\\lib", "[svelte]": { "editor.defaultFormatter": "svelte.svelte-vscode" - }, - "css.customData": [".vscode/tailwind.json"] + } } diff --git a/.vscode/tailwind.json b/.vscode/tailwind.json deleted file mode 100644 index a45bccc..0000000 --- a/.vscode/tailwind.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "version": 1.1, - "atDirectives": [ - { - "name": "@tailwind", - "description": "Use the `@tailwind` directive to insert Tailwind's `base`, `components`, `utilities` and `screens` styles into your CSS.", - "references": [ - { - "name": "Tailwind Documentation", - "url": "https://tailwindcss.com/docs/functions-and-directives#tailwind" - } - ] - }, - { - "name": "@apply", - "description": "Use the `@apply` directive to inline any existing utility classes into your own custom CSS. This is useful when you find a common utility pattern in your HTML that youโ€™d like to extract to a new component.", - "references": [ - { - "name": "Tailwind Documentation", - "url": "https://tailwindcss.com/docs/functions-and-directives#apply" - } - ] - }, - { - "name": "@responsive", - "description": "You can generate responsive variants of your own classes by wrapping their definitions in the `@responsive` directive:\n```css\n@responsive {\n .alert {\n background-color: #E53E3E;\n }\n}\n```\n", - "references": [ - { - "name": "Tailwind Documentation", - "url": "https://tailwindcss.com/docs/functions-and-directives#responsive" - } - ] - }, - { - "name": "@screen", - "description": "The `@screen` directive allows you to create media queries that reference your breakpoints by **name** instead of duplicating their values in your own CSS:\n```css\n@screen sm {\n /* ... */\n}\n```\nโ€ฆgets transformed into this:\n```css\n@media (min-width: 640px) {\n /* ... */\n}\n```\n", - "references": [ - { - "name": "Tailwind Documentation", - "url": "https://tailwindcss.com/docs/functions-and-directives#screen" - } - ] - }, - { - "name": "@variants", - "description": "Generate `hover`, `focus`, `active` and other **variants** of your own utilities by wrapping their definitions in the `@variants` directive:\n```css\n@variants hover, focus {\n .btn-brand {\n background-color: #3182CE;\n }\n}\n```\n", - "references": [ - { - "name": "Tailwind Documentation", - "url": "https://tailwindcss.com/docs/functions-and-directives#variants" - } - ] - } - ] -} diff --git a/README.md b/README.md index 38235d5..a7e6442 100644 --- a/README.md +++ b/README.md @@ -1,25 +1,29 @@
- npm + npm - bundle + bundle - license + license - docs + docs
-[![Carta.png](https://i.postimg.cc/nV6DMXKM/Carta.png)](https://beartocode.github.io/carta/) +
+ banner +
-

Carta

-
Modern, lightweight, powerful Markdown Editor.
+
+ +
Carta
+
Swiftly edit and render Markdown, with no overhead.

-๐Ÿ“š Documentation +Documentation ยท GitHub
@@ -28,30 +32,22 @@ # Introduction -> [!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. +Carta is a **lightweight**, **fast** and **extensible** Svelte Markdown editor and viewer, based on [Marked](https://github.com/markedjs/marked). Check out the [demo](http://beartocode.github.io/carta/) 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. ## Features -- ๐ŸŒˆ 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; -- ๐Ÿ”€ 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 (plugin); -- ๐ŸŒˆ Code blocks **syntax highlighting** (plugin). +- 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). ## Packages @@ -64,23 +60,12 @@ Differently from most editors, Carta does not include a code editor, but it is _ | [plugin-slash](https://www.npmjs.com/package/@cartamd/plugin-slash) | ![plugin-slash](https://img.shields.io/npm/v/@cartamd/plugin-slash) | [/plugins/slash](https://beartocode.github.io/carta/plugins/slash) | | [plugin-tikz](https://www.npmjs.com/package/@cartamd/plugin-tikz) | ![plugin-tikz](https://img.shields.io/npm/v/@cartamd/plugin-tikz) | [/plugins/tikz](https://beartocode.github.io/carta/plugins/tikz) | | [plugin-attachment](https://www.npmjs.com/package/@cartamd/plugin-attachment) | ![plugin-attachment](https://img.shields.io/npm/v/@cartamd/plugin-attachment) | [/plugins/attachment](https://beartocode.github.io/carta/plugins/attachment) | -| [plugin-anchor](https://www.npmjs.com/package/@cartamd/plugin-anchor) | ![plugin-anchor](https://img.shields.io/npm/v/@cartamd/plugin-anchor) | [/plugins/anchor](https://beartocode.github.io/carta/plugins/anchor) | - -## Community plugins - -| Plugin | Description | -| ----------------------------------------------------------------------------- | ---------------------------------- | -| [carta-plugin-video](https://github.com/maisonsmd/carta-plugin-video) | Render online videos | -| [carta-plugin-imsize](https://github.com/maisonsmd/carta-plugin-imsize) | Render images in specific sizes | -| [carta-plugin-subscript](https://github.com/maisonsmd/carta-plugin-subscript) | Render subscripts and superscripts | -| [carta-plugin-ins-del](https://github.com/maisonsmd/carta-plugin-ins-del) | `` and `` tags support | # Getting started -> [!WARNING] +> **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 @@ -100,9 +85,11 @@ npm i @cartamd/plugin-name ```svelte - + ``` @@ -137,7 +123,6 @@ For the full documentation, examples, guides and more checkout the [website](htt - [Slash](https://beartocode.github.io/carta/plugins/slash) - [TikZ](https://beartocode.github.io/carta/plugins/tikz) - [Attachment](https://beartocode.github.io/carta/plugins/attachment) - - [Anchor](https://beartocode.github.io/carta/plugins/anchor) - API: - [Utilities](https://beartocode.github.io/carta/api/utilities) - [Core](https://beartocode.github.io/carta/api/core) @@ -158,12 +143,3 @@ npm run commit # or, if you have commitizen installed globally git cz ``` - -### Running docs - -If you want to preview the docs: - -``` -cd docs -npm run dev -``` diff --git a/docs/package.json b/docs/package.json index 7a24ff5..b8127ee 100644 --- a/docs/package.json +++ b/docs/package.json @@ -15,11 +15,9 @@ "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch" }, "devDependencies": { - "@sveltejs/adapter-auto": "^3.1.1", - "@sveltejs/adapter-static": "3.0.1", - "@sveltejs/kit": "^2.5.4", - "@sveltejs/package": "^2.3.0", - "@sveltejs/vite-plugin-svelte": "^3.0.2", + "@sveltejs/adapter-auto": "^2.0.0", + "@sveltejs/adapter-static": "1.0.0-next.50", + "@sveltejs/kit": "^1.5.0", "@types/flexsearch": "^0.7.6", "@types/katex": "^0.16.0", "autoprefixer": "^10.4.16", @@ -27,12 +25,12 @@ "rehype-autolink-headings": "^7.1.0", "rehype-slug": "^6.0.0", "sass": "^1.69.5", - "svelte": "^4.2.12", - "svelte-check": "^3.6.7", + "svelte": "^3.54.0 || ^4.0.0", + "svelte-check": "^3.0.1", "tailwindcss": "^3.3.5", "tslib": "^2.4.1", "typescript": "^5.0.0", - "vite": "^5.1.6" + "vite": "^4.3.9" }, "type": "module", "dependencies": { @@ -47,8 +45,8 @@ "clsx": "^2.0.0", "cmdk-sv": "^0.0.6", "flexsearch": "0.7.21", - "iconify-icon": "^2.0.0", - "katex": "^0.16.10", + "katex": "^0.16.7", + "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 8be7d1f..f0b289b 100644 --- a/docs/src/lib/components/code/Code.svelte +++ b/docs/src/lib/components/code/Code.svelte @@ -1,4 +1,6 @@ @@ -11,10 +13,10 @@ navigator.clipboard.writeText(elem.innerText); }} class=" - 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 + 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 " > - + diff --git a/docs/src/lib/components/header-tracker/HeaderTracker.svelte b/docs/src/lib/components/header-tracker/HeaderTracker.svelte index d584c97..f5a6b1d 100644 --- a/docs/src/lib/components/header-tracker/HeaderTracker.svelte +++ b/docs/src/lib/components/header-tracker/HeaderTracker.svelte @@ -1,7 +1,5 @@ - { - throttledHighlightHeader(); - debouncedHighlightHeader(); // So it is called at the end of the scroll event - }} -/> +
{#each headers as header, i} {@const margin = Number(header.tagName.split('')[1]) - 1} - {#key selectedHeaderIndex} - {#if header.children[0] instanceof HTMLAnchorElement && header.children[0].href} + {@const nextHeader = headers[i + 1]} + {#if header.children[0] instanceof HTMLAnchorElement && header.children[0].href} + {#key scrollY} {header.innerText} - {/if} - {/key} + {/key} + {/if} {/each}
diff --git a/docs/src/lib/components/link/PluginLink.svelte b/docs/src/lib/components/link/PluginLink.svelte deleted file mode 100644 index 8318e91..0000000 --- a/docs/src/lib/components/link/PluginLink.svelte +++ /dev/null @@ -1,22 +0,0 @@ - - - - - diff --git a/docs/src/lib/components/mobile-sidebar/MobileSidebar.svelte b/docs/src/lib/components/mobile-sidebar/MobileSidebar.svelte index 1ebb918..220ed85 100644 --- a/docs/src/lib/components/mobile-sidebar/MobileSidebar.svelte +++ b/docs/src/lib/components/mobile-sidebar/MobileSidebar.svelte @@ -1,4 +1,5 @@
- + - + Close diff --git a/docs/src/lib/examples/DiscordExample.svelte b/docs/src/lib/examples/DiscordExample.svelte index bfc048a..462bbd2 100644 --- a/docs/src/lib/examples/DiscordExample.svelte +++ b/docs/src/lib/examples/DiscordExample.svelte @@ -1,13 +1,12 @@ - + diff --git a/docs/src/lib/examples/GitHubExample.svelte b/docs/src/lib/examples/GitHubExample.svelte index 5de31c6..444f718 100644 --- a/docs/src/lib/examples/GitHubExample.svelte +++ b/docs/src/lib/examples/GitHubExample.svelte @@ -1,14 +1,13 @@ - + diff --git a/docs/src/lib/examples/MathStackExchangeExample.svelte b/docs/src/lib/examples/MathStackExchangeExample.svelte index c6057b1..907ef09 100644 --- a/docs/src/lib/examples/MathStackExchangeExample.svelte +++ b/docs/src/lib/examples/MathStackExchangeExample.svelte @@ -1,14 +1,13 @@
- + {#key value} - + {/key}
diff --git a/docs/src/lib/examples/assets/PlusIcon.svelte b/docs/src/lib/examples/assets/PlusIcon.svelte deleted file mode 100644 index aaa4ef9..0000000 --- a/docs/src/lib/examples/assets/PlusIcon.svelte +++ /dev/null @@ -1,3 +0,0 @@ -
- -
diff --git a/docs/src/lib/search/index.ts b/docs/src/lib/search/index.ts index 7a1623f..511f862 100644 --- a/docs/src/lib/search/index.ts +++ b/docs/src/lib/search/index.ts @@ -1,4 +1,4 @@ -import flexsearch from 'flexsearch'; +import { Document } from 'flexsearch'; import type { SvelteComponent } from 'svelte'; export interface SearchResult { @@ -19,7 +19,7 @@ export type EnrichedSearchResult = SearchResult & { }; export async function initializeSearch() { - const indexedPages = new flexsearch.Document({ + const indexedPages = new Document({ tokenize: 'full', cache: true, context: true, diff --git a/docs/src/lib/styles/discord.scss b/docs/src/lib/styles/discord.scss index 60d8d3b..ad88fd9 100644 --- a/docs/src/lib/styles/discord.scss +++ b/docs/src/lib/styles/discord.scss @@ -27,7 +27,6 @@ .carta-font-code { font-family: 'Fira Code', monospace; caret-color: white; - font-size: 1.1rem; } .carta-toolbar { @@ -42,6 +41,10 @@ height: 1.75rem; transform: translateX(-50%) translateY(-50%); } + + [class*='shj-lang-'] { + background: transparent; + } } // Plugin emoji @@ -76,8 +79,3 @@ background: $background-contrast; } } - -html.dark .shiki, -html.dark .shiki span { - color: var(--shiki-dark) !important; -} diff --git a/docs/src/lib/styles/github.scss b/docs/src/lib/styles/github.scss index 7d2b961..b83daaf 100644 --- a/docs/src/lib/styles/github.scss +++ b/docs/src/lib/styles/github.scss @@ -28,14 +28,15 @@ .carta-font-code { font-family: 'Fira Code', monospace; caret-color: white; - font-size: 1.1rem; } .carta-toolbar { height: 2.5rem; background-color: $background-light; + border-bottom: 1px solid $border; + padding-right: 12px; border-top-left-radius: 0.5rem; border-top-right-radius: 0.5rem; @@ -50,12 +51,6 @@ } } - .carta-toolbar-left button, - .carta-toolbar-right, - .carta-filler { - border-bottom: 1px solid $border; - } - .carta-toolbar-left { & > *:first-child { border-top-left-radius: 0.5rem; @@ -67,12 +62,10 @@ font-size: 0.95rem; } - button { - height: 100%; - } - .carta-active { + height: 100%; background-color: $background; + transform: translateY(1px); color: white; border-right: 1px solid $border; @@ -84,37 +77,8 @@ } } - .carta-toolbar-right { - padding-right: 12px; - } - - .carta-icons-menu { - padding: 8px; - border: 1px solid $border; - border-radius: 6px; - min-width: 180px; - background: $background; - - .carta-icon-full { - padding-left: 6px; - padding-right: 6px; - - margin-top: 2px; - &:first-child { - margin-top: 0; - } - - &:hover { - color: white; - background-color: $border; - } - - span { - margin-left: 6px; - color: white; - font-size: 0.85rem; - } - } + [class*='shj-lang-'] { + background: transparent; } } @@ -196,8 +160,3 @@ text-overflow: ellipsis; } } - -html.dark .shiki, -html.dark .shiki span { - color: var(--shiki-dark) !important; -} diff --git a/docs/src/lib/styles/markdown.scss b/docs/src/lib/styles/markdown.scss index 61eb539..d42cd16 100644 --- a/docs/src/lib/styles/markdown.scss +++ b/docs/src/lib/styles/markdown.scss @@ -43,21 +43,9 @@ } code { - @apply rounded bg-neutral-800 px-1 text-neutral-50; - } - - p, - h1, - h2, - h3 { - code { - @apply px-1; + @apply rounded; + &:not([class*='language-']) { + @apply bg-neutral-800 px-1 text-neutral-100; } } - - .carta-editor code { - font-family: 'Fira Code', monospace; - background: transparent; - padding: 0; - } } diff --git a/docs/src/lib/styles/math-stack-exchange.scss b/docs/src/lib/styles/math-stack-exchange.scss index 1354a4e..73ec59e 100644 --- a/docs/src/lib/styles/math-stack-exchange.scss +++ b/docs/src/lib/styles/math-stack-exchange.scss @@ -34,7 +34,6 @@ .carta-font-code { font-family: 'Fira Code', monospace; caret-color: white; - font-size: 1.1rem; } .carta-toolbar { @@ -65,34 +64,9 @@ .carta-toolbar-right { justify-content: flex-start; } - } - .carta-icons-menu { - padding: 8px; - border: 1px solid $border; - border-radius: 6px; - min-width: 180px; - background: $background; - - .carta-icon-full { - padding-left: 6px; - padding-right: 6px; - - margin-top: 2px; - &:first-child { - margin-top: 0; - } - - &:hover { - color: white; - background-color: $border; - } - - span { - margin-left: 6px; - color: white; - font-size: 0.85rem; - } + [class*='shj-lang-'] { + background: transparent; } } @@ -101,8 +75,3 @@ padding: 1rem; } } - -html.dark .shiki, -html.dark .shiki span { - color: var(--shiki-dark) !important; -} diff --git a/docs/src/lib/utils.ts b/docs/src/lib/utils.ts index d2b288e..eba19d8 100644 --- a/docs/src/lib/utils.ts +++ b/docs/src/lib/utils.ts @@ -54,41 +54,3 @@ export const flyAndScale = ( easing: cubicOut }; }; - -export const throttle = ( - fn: (...args: A) => R, - delay: number -): [(...args: A) => R | undefined, () => void] => { - let wait = false; - let timeout: undefined | number; - let cancelled = false; - - return [ - (...args: A) => { - if (cancelled) return undefined; - if (wait) return undefined; - - const val = fn(...args); - - wait = true; - - timeout = window.setTimeout(() => { - wait = false; - }, delay); - - return val; - }, - () => { - cancelled = true; - clearTimeout(timeout); - } - ]; -}; - -export function debounce(cb: (...args: T) => unknown, wait = 1000) { - let timeout: NodeJS.Timeout; - return (...args: T) => { - clearTimeout(timeout); - timeout = setTimeout(() => cb(...args), wait); - }; -} diff --git a/docs/src/pages/api/core.svelte.md b/docs/src/pages/api/core.svelte.md index 62163f9..4f003a7 100644 --- a/docs/src/pages/api/core.svelte.md +++ b/docs/src/pages/api/core.svelte.md @@ -17,15 +17,9 @@ new Carta({ }); ``` -### `gfmOptions` - -Type: `GfmOptions` - -GitHub Flavored Markdown options. - ### `extensions` -Type: `Extension[]` +Type: `CartaExtension[]` List of extensions(plugins) to use. @@ -40,19 +34,13 @@ Defaults to 300ms. Type: `DefaultShortcutId[] | true` -Remove default shortcuts by id. You can use `true` to disable all of them. - -### `disableIcons` - -Type: `DefaultIconId[] | true` - -Remove default icons by id. You can use `true` to disable all of them. +Remove shortcuts by id. You can use `true` to disable all of them. ### `disablePrefixes` Type: `DefaultPrefixId[] | true` -Remove default prefixes by id. You can use `true` to disable all of them. +Remove prefixes by id. You can use `true` to disable all of them. ### `historyOptions` @@ -78,21 +66,9 @@ Type: `(html: string) => void` HTML sanitizer. See [here]({base}/getting-started#sanitization) for more details. -### `shikiOptions` +# `CartaEditor` options -Type: `ShikiOptions` - -Highlighter(Shiki) options. - -### `theme` - -Type: `Theme | DualTheme` - -Shiki theme to use to highlight Markdown. - -# `MarkdownEditor` options - -List of options that can be used in the `` component. +List of options that can be used in the `` component. ### `carta` @@ -136,23 +112,9 @@ Type: `string` Set the textarea placeholder. -### `textarea` +# `CartaViewer` options -Type: `TextAreaProps` (extends `Record`) - -Additional properties that will be used in the textarea used under the hood in the editor. -`class`, `placeholder` and `value` are not allowed. Use the corresponding editor properties -instead. - -### `labels` - -Type: `Partial` - -Can be used to provide custom text for labels in the editor. - -# `Markdown` options - -List of options that can be used in the `` component. +List of options that can be used in the `` component. ### `carta` diff --git a/docs/src/pages/api/extension.svelte.md b/docs/src/pages/api/extension.svelte.md index f39da6a..a871742 100644 --- a/docs/src/pages/api/extension.svelte.md +++ b/docs/src/pages/api/extension.svelte.md @@ -7,14 +7,14 @@ title: Extension import Code from '$lib/components/code/Code.svelte'; -# `Plugin` properties +# `CartaExtension` properties You can easily extend Carta by creating custom plugins. ```ts -const ext: Plugin = { +const ext: CartaExtension = { // ... }; @@ -25,47 +25,11 @@ const carta = new Carta({ -Here are all the `Plugin` properties: +Here are all the `CartaExtension` properties: -### `transformers` +### `markedExtensions` -Type: `UnifiedTransformer` - -Remark or Rehype transformers. - -#### `UnifiedTransformer.execution` - -Type: `'sync' | 'async'` - -If you specify async, this transformer won't be available for SSR. - -#### `UnifiedTransformer.type` - -Type: `'remark' | 'rehype'` - -This determines at which step the transformer will operate, whether on Remark, on a Markdown-based syntax tree, or Rehype, on a HTML-based one. - -#### `UnifiedTransformer.transform` - -Type: `({ processor, carta }) => void` - -The actual processor, can be async if the execution is specified as such. - - - -```ts -{ - execution: 'sync', - type: 'rehype', - transform({ processor }) { - processor - .use(rehypeSlug) - .use(rehypeAutolinkHeadings); - } -} -``` - - +List of marked extensions. For more information check out [Marked docs](https://marked.js.org/using_pro). ### `shortcuts` @@ -99,7 +63,7 @@ Set of keys, corresponding to the `e.key` of `KeyboardEvent`s, but lowercase. #### `KeyboardShortcut.action` -Type: `(input: InputEnhancer) => void` +Type: `(input: CartaInput) => void` Shortcut callback. @@ -109,14 +73,14 @@ Prevent saving the current state in history. ### `icons` -Type: `Icon[]` +Type: `CartaIcon[]` Additional toolbar icons. For example: ```ts -const icon: Icon = { +const icon: CartaIcon = { id: 'heading', action: (input) => input.toggleLinePrefix('###'), component: HeadingIcon @@ -125,19 +89,19 @@ const icon: Icon = { -#### `Icon.id` +#### `CartaIcon.id` Type: `string` Id of the icon. -#### `Icon.action` +#### `CartaIcon.action` -Type: `(input: InputEnhancer) => void` +Type: `(input: CartaInput) => void` Click callback. -#### `Icon.component` +#### `CartaIcon.component` Type: `ComponentType` (SvelteComponent) @@ -198,15 +162,15 @@ const prefix: Prefix = { ### `listeners` -Type: `Listener[]` +Type: `CartaListener[]` Textarea event listeners. Has an additional `carta-render` and `carta-render-ssr` events keys. ```ts -const click: Listener = ['click', () => console.log('I was clicked!')]; -const render: Listener = [ +const click: CartaListener = ['click', () => console.log('I was clicked!')]; +const render: CartaListener = [ 'carta-render', (e) => { const carta = e.detail.carta; @@ -222,39 +186,33 @@ const render: Listener = [ ### `components` -Type: `ExtensionComponent[]` +Type: `CartaExtensionComponent[]` Additional components to be added to the editor or viewer. -#### `ExtensionComponent.component` +#### `CartaExtensionComponent.component` Type: `typeof SvelteComponentTyped` Svelte components that exports `carta: Carta` and all the other properties specified as the generic parameter and in `props`. -#### `ExtensionComponent.props` +#### `CartaExtensionComponent.props` Type: `T` Properties that will be handed to the component. -#### `ExtensionComponent.parent` +#### `CartaExtensionComponent.parent` Type: `MaybeArray<'editor' | 'input' | 'renderer' | 'preview'>` Where the element will be placed. -### `grammarRules` - -Type: `GrammarRule[]` - -Custom Markdown TextMate grammar rules for Shiki. They will be injected into the language. - ### `highlightRules` -Type: `HighlightingRule[]` +Type: `ShjLanguageDefinition` -Custom highlighting rules for ShiKi. They will be injected into the selected theme. +Custom markdown highlighting rules. See [Speed-Highlight Wiki](https://github.com/speed-highlight/core/wiki/Create-or-suggest-new-languages) for more info. ### `onLoad` diff --git a/docs/src/pages/api/utilities.svelte.md b/docs/src/pages/api/utilities.svelte.md index 273796f..c641125 100644 --- a/docs/src/pages/api/utilities.svelte.md +++ b/docs/src/pages/api/utilities.svelte.md @@ -40,52 +40,3 @@ Svelte action that allows you to bind a specific element to the caret position.
``` - -## `Carta.highlighter` - -Get the Shiki highlighter. - -```ts -const highlighter = await carta.highlighter(); -const userTheme = carta.theme; -``` - -Here are some other highlight related utilities: - -### `isBundleLanguage` - -Checks if a language is a bundled language. - -```ts -export const isBundleLanguage = (lang: string): lang is BundledLanguage; -``` - -### `isBundleTheme` - -Checks if a theme is a bundled theme. - -```ts -export const isBundleTheme = (theme: string): theme is BundledTheme; -``` - -### `isDualTheme` - -Checks if a theme is a dual theme. - -```ts -export const isDualTheme = (theme: Theme | DualTheme): theme is DualTheme; -``` - -### `isSingleTheme` - -```ts -export const isSingleTheme = (theme: Theme | DualTheme): theme is Theme; -``` - -### `isThemeRegistration` - -Checks if a theme is a theme registration. - -```ts -export const isThemeRegistration = (theme: Theme): theme is ThemeRegistration; -``` diff --git a/docs/src/pages/community-plugins.svelte.md b/docs/src/pages/community-plugins.svelte.md deleted file mode 100644 index c30ce68..0000000 --- a/docs/src/pages/community-plugins.svelte.md +++ /dev/null @@ -1,83 +0,0 @@ ---- -title: Community Plugins -section: Overview ---- - - - -Here are is a list of several plugins developed by the community: - - - -### `carta-plugin-video` - - - -> Adds ability to render online video from Youtube or Vimeo. - - - -``` -npm i carta-plugin-video -``` - - - - - -### `carta-plugin-imsize` - - - -> Adds ability to render images in specific sizes. - - - -``` -npm i carta-plugin-imsize -``` - - - - - -### `carta-plugin-ins-del` - - - -> `` and `` tags support - - - -``` -npm i carta-plugin-ins-del -``` - - - - - -### `carta-plugin-subscript` - - - -> Adds ability to render subscripts and superscripts. - - - -``` -npm i carta-plugin-subscript -``` - - diff --git a/docs/src/pages/editing-styles.svelte.md b/docs/src/pages/editing-styles.svelte.md index 81736ed..1752008 100644 --- a/docs/src/pages/editing-styles.svelte.md +++ b/docs/src/pages/editing-styles.svelte.md @@ -43,68 +43,11 @@ While the core styles are embedded in the Svelte components, the others can be s ### Using multiple themes -By using the `theme` property in `` you can differentiate the themes of multiple editors. +By using the `theme` property in the editor you can differentiate the themes of multiple editors. -## Dark mode +## Changing Markdown color theme -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: - - - -```ts -const carta = new Carta({ - // ... - theme: 'github-dark' -}); -``` - - - -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: - - - -```ts -const carta = new Carta({ - // ... - shikiOptions: { - langs: // ... - themes: // ... - } -}) -``` - - +Carta uses [Speed Highlight JS](https://github.com/speed-highlight/core) for syntax highlighting. Two default themes are included in the core package, `light.css` and `dark.css`, and others can be found on the Speed Highlight [GitHub](https://github.com/speed-highlight/core/tree/main/src/themes), but you can also easily create your own. ## Markdown stylesheets diff --git a/docs/src/pages/getting-started.svelte.md b/docs/src/pages/getting-started.svelte.md index 81b7662..71ed52d 100644 --- a/docs/src/pages/getting-started.svelte.md +++ b/docs/src/pages/getting-started.svelte.md @@ -37,8 +37,9 @@ Setup a basic editor: ```svelte - + ``` @@ -68,7 +68,7 @@ Or, if you just want to render content: ```svelte - + ``` @@ -93,16 +93,16 @@ Since Carta operates both on the server and the client, you'd need a sanitizer a ```svelte - + ``` diff --git a/docs/src/pages/introduction.svelte.md b/docs/src/pages/introduction.svelte.md index 12e0af9..27450dd 100644 --- a/docs/src/pages/introduction.svelte.md +++ b/docs/src/pages/introduction.svelte.md @@ -5,21 +5,20 @@ section: Overview -> Modern, lightweight, powerful Markdown Editor. +> Swiftly edit and render Markdown, with no overhead. Carta is a lightweight, fast and extensible Svelte Markdown editor and viewer, designed for flexibility. It works natively in SvelteKit, and supports Server Side Rendering. -## Features +## Core Features -- ๐ŸŒˆ 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. -- ๐Ÿ”€ Scroll sync; -- โœ… Accessibility friendly; -- ๐Ÿ–ฅ๏ธ **SSR** compatible; +- **Lightweight**: no code editor is included, just a textarea with syntax highlighting, with Markdown related utilities. +- **SSR compatible**: works great with SvelteKit. +- **Keyboard shortcuts**: extensible and configurable. +- **Toolbar**: add or remove buttons according to your needs. +- **Plugins friendly**: easily create your own extension. ## Official Plugins @@ -31,7 +30,7 @@ Carta comes with a set of official plugins for the most common use cases. - + Math Support for KaTex expressions. @@ -39,7 +38,7 @@ Carta comes with a set of official plugins for the most common use cases. - + Code Code blocks syntax highlighting. @@ -47,7 +46,7 @@ Carta comes with a set of official plugins for the most common use cases. - + Emoji Embed emojis in Markdown. @@ -55,7 +54,7 @@ Carta comes with a set of official plugins for the most common use cases. - + Slash Support for slash commands. @@ -63,7 +62,7 @@ Carta comes with a set of official plugins for the most common use cases. - + TikZ Support for TikZ/PgfPlots diagrams. @@ -71,28 +70,12 @@ Carta comes with a set of official plugins for the most common use cases. - + Attachment Handle text attachments. - - - -Anchor -Add anchor links to headings. - - - - - - -Community Plugins -Explore plugins from the community. - - - ## Examples @@ -105,7 +88,7 @@ A list of examples inspired by popular platforms. - + GitHub Inspired by GitHub. @@ -113,7 +96,7 @@ A list of examples inspired by popular platforms. - + Discord Inspired by Discord. @@ -121,7 +104,7 @@ A list of examples inspired by popular platforms. - + Math Stack Exchange Inspired by Math Stack Exchange. diff --git a/docs/src/pages/migration.svelte.md b/docs/src/pages/migration.svelte.md deleted file mode 100644 index 72d25dc..0000000 --- a/docs/src/pages/migration.svelte.md +++ /dev/null @@ -1,57 +0,0 @@ ---- -title: Migration Guide -section: Overview ---- - -# Major Changes - -## Removal of Marked - -Marked has been replaced with a combination of Unified, Remark and Rehype. If you previously used a custom plugin with it, you'll have to update it manually. Otherwise, all builtin plugins have already been updated. Make sure to **update** them! - -Some plugins now have a different implementation and their options have changed. Those plugins are [plugin-math](https://beartocode.github.io/carta/plugins/math) and [plugin-anchor](https://beartocode.github.io/carta/plugins/anchor). - -## Syntax highlighter update - -SpeedHighlight has been replaced with [Shiki](https://shiki.matsu.io/). It now offers support for more languages, themes, and extensibility. - -Make sure to remove previous themes imports, as Shiki uses JS based ones. - -```ts -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-'] { - /* ... */ -} -``` - -## Removed verbose prefixes - -Many exports have been renamed to make them less verbose: - -- `CartaEditor` -> `MarkdownEditor` (old one still supported); -- `CartaRenderer` -> `Markdown` (old one still supported); -- `CartaEvent` -> `Event`; -- `CartaEventType` -> `EventType`; -- `CartaExtension` -> `Plugin`; -- `CartaExtensionComponent` -> `ExtensionComponent`; -- `CartaOptions` -> `Options`; -- `CartaHistory` -> `TextAreaHistory`; -- `CartaHistoryOptions` -> `TextAreaHistoryOptions`; -- `CartaIcon` -> `Icon`; -- `CartaListener` -> `Listener`; -- `CartaInput` -> `InputEnhancer`; -- `CartaRenderer` -> `Renderer`; -- `CartaLabels` -> `Labels`; - -# 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; -- Removed deprecated options `postProcess` for `plugin-tikz`; -- `Carta.options` are no longer available. diff --git a/docs/src/pages/plugins/anchor.svelte.md b/docs/src/pages/plugins/anchor.svelte.md deleted file mode 100644 index 4b17150..0000000 --- a/docs/src/pages/plugins/anchor.svelte.md +++ /dev/null @@ -1,70 +0,0 @@ ---- -section: Plugins -title: Anchor ---- - - - -This plugin adds `id` attributes and permalinks to headings. - -## Installation - - - -``` -npm i @cartamd/plugin-anchor -``` - - - -## Setup - -### Styles - -Import the default theme, or create you own: - - - -```ts -import '@cartamd/plugin-anchor/default.css'; -``` - - - -### Extension - - - -```svelte - - - -``` - - - -## Options - -Here are the options you can pass to `anchor()`: - -```ts -export interface AnchorExtensionOptions { - /** - * rehype-slug options. - */ - slug?: SlugOptions; - /** - * rehype-autolink-headings options. - */ - autolink?: AutolinkOptions; -} -``` diff --git a/docs/src/pages/plugins/attachment.svelte.md b/docs/src/pages/plugins/attachment.svelte.md index bbd0eca..2543c3d 100644 --- a/docs/src/pages/plugins/attachment.svelte.md +++ b/docs/src/pages/plugins/attachment.svelte.md @@ -35,7 +35,7 @@ import '@cartamd/plugin-attachment/default.css'; ```svelte - + ``` diff --git a/docs/src/pages/plugins/code.svelte.md b/docs/src/pages/plugins/code.svelte.md index d1c2c82..7d089da 100644 --- a/docs/src/pages/plugins/code.svelte.md +++ b/docs/src/pages/plugins/code.svelte.md @@ -7,7 +7,7 @@ title: Code import Code from '$lib/components/code/Code.svelte'; -This plugin adds support for code blocks **syntax highlighting**. It uses the same highlighter from the core package(Shiki). +This plugin adds support for code blocks **syntax highlighting**. ## Installation @@ -19,6 +19,8 @@ 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 @@ -35,34 +37,34 @@ 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. +The theme is the same as the one used in the main Carta package (`carta-md/light.css` or `carta-md/dark.css`). +[Here](https://github.com/speed-highlight/core/tree/main/src/themes) you can find other themes. + +### Using a custom highlighter + +You can also provide a custom highlighter, that can be either sync or async. ```ts -const carta = new Carta({ - // ... - extensions: [ - code({ - theme: 'ayu-light' - }) - ] +code({ + customHighlight: { + highlighter: (code, lang) => myCustomHighlighter(code, lang), + langPrefix: 'my-highlighter-' + } }); ``` -### Using a custom highlighter - -It is no longer possible to specify a custom highlighter in this plugin. However, there are many different [Remark plugins](https://github.com/remarkjs/remark/blob/main/doc/plugins.md#list-of-plugins) that provide syntax highlighting. - ### Extension ```svelte - + ``` ## Options -The options you can pass to `code()` extend the ones provided by [Shiki](https://shiki.matsu.io/guide/transformers). +Here are the options you can pass to `code()`: + +```ts +interface CodeExtensionOptions { + /** + * Default language when none is provided. + */ + defaultLanguage?: string; + /** + * Whether to autodetect a language when none is provided. + * Overwritten by `defaultLanguage`. + */ + autoDetect?: string; + /** + * Line numbering. + * @defaults false. + */ + lineNumbering?: boolean; + + /** + * Options for custom syntax highlighting. + */ + customHighlight?: { + /** + * Custom highlight function. Beware that you'll have to provide your own styles. + * This function needs to convert a string of code into html. + */ + highlighter: (code: string, lang: string) => string | Promise; + /** + * The language tag found immediately after the code block opening marker is + * appended to this to form the class attribute added to the `` element. + */ + langPrefix: string; + }; +} +``` diff --git a/docs/src/pages/plugins/emoji.svelte.md b/docs/src/pages/plugins/emoji.svelte.md index e7162bd..df7fa01 100644 --- a/docs/src/pages/plugins/emoji.svelte.md +++ b/docs/src/pages/plugins/emoji.svelte.md @@ -39,7 +39,7 @@ import '@cartamd/plugin-emoji/default.css'; ```svelte - + ``` diff --git a/docs/src/pages/plugins/math.svelte.md b/docs/src/pages/plugins/math.svelte.md index 7d4cc5c..a7691fd 100644 --- a/docs/src/pages/plugins/math.svelte.md +++ b/docs/src/pages/plugins/math.svelte.md @@ -5,7 +5,7 @@ title: Math - + ``` @@ -103,7 +103,7 @@ Pythagorean theorem: $a^2+b^2=c^2$ - +
@@ -119,7 +119,7 @@ $$ - + ## Options @@ -131,6 +131,7 @@ interface MathExtensionOptions { * Options for inline katex, eg: $a^2+b^2=c^2$ */ inline?: { + katexOptions?: KatexOptions; /** * @default control+m */ @@ -143,18 +144,23 @@ interface MathExtensionOptions { * $$ */ block?: { + /** + * Tag the generated katex will be put into. Must have `display: block`. + */ + tag?: string; + /** + * Whether to center the generated expression. + * @default true + */ + center?: boolean; + /** + * Class for generated katex. + */ + class?: string; /** * @default ctrl+shift+m */ shortcut?: Set; + katexOptions?: KatexOptions; }; - /** - * Options for remark-math - */ - remarkMath?: RemarkMathOptions; - /** - * Options for rehype-katex - */ - rehypeKatex?: RehypeKatexOptions; -} ``` diff --git a/docs/src/pages/plugins/slash.svelte.md b/docs/src/pages/plugins/slash.svelte.md index 5593a72..cc029cb 100644 --- a/docs/src/pages/plugins/slash.svelte.md +++ b/docs/src/pages/plugins/slash.svelte.md @@ -39,7 +39,7 @@ import '@cartamd/plugin-slash/default.css'; ```svelte - + ``` diff --git a/docs/src/pages/plugins/tikz.svelte.md b/docs/src/pages/plugins/tikz.svelte.md index c878f8a..7557c42 100644 --- a/docs/src/pages/plugins/tikz.svelte.md +++ b/docs/src/pages/plugins/tikz.svelte.md @@ -20,7 +20,7 @@ npm i @cartamd/plugin-tikz ## Important Notes 1. This plugin requires the import of a **heavy** library (~7Mb), which is dynamically imported at runtime; -2. Generated images are **not SSR compatible**, as they are rendered in the browser; +2. Generated images are **not ssr compatible**, as they are rendered in the browser; 3. You need to update your sanitizer to allow the specific tag: `
`. ## Setup @@ -29,7 +29,7 @@ npm i @cartamd/plugin-tikz ```svelte - + ``` diff --git a/docs/src/pages/using-components.svelte.md b/docs/src/pages/using-components.svelte.md deleted file mode 100644 index f301c51..0000000 --- a/docs/src/pages/using-components.svelte.md +++ /dev/null @@ -1,217 +0,0 @@ ---- -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, 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). diff --git a/docs/src/routes/+layout.svelte b/docs/src/routes/+layout.svelte index 723f83f..7bd40fa 100644 --- a/docs/src/routes/+layout.svelte +++ b/docs/src/routes/+layout.svelte @@ -4,7 +4,6 @@ import Navbar from '$lib/components/navbar/Navbar.svelte'; import Sidebar from '$lib/components/sidebar/Sidebar.svelte'; import Footer from '$lib/components/footer/Footer.svelte'; - import { base } from '$app/paths'; import '../app.postcss'; @@ -13,7 +12,7 @@
@@ -24,6 +23,6 @@
-
diff --git a/docs/src/routes/+layout.ts b/docs/src/routes/+layout.ts index a4c5a95..189f71e 100644 --- a/docs/src/routes/+layout.ts +++ b/docs/src/routes/+layout.ts @@ -1,3 +1 @@ -import 'iconify-icon'; // Register iconify web components - export const prerender = true; diff --git a/docs/src/routes/+page.svelte b/docs/src/routes/+page.svelte index ac2153e..b5fbaae 100644 --- a/docs/src/routes/+page.svelte +++ b/docs/src/routes/+page.svelte @@ -1,9 +1,8 @@ diff --git a/docs/src/routes/[...slug]/+page.svelte b/docs/src/routes/[...slug]/+page.svelte index 449ea7b..a0df694 100644 --- a/docs/src/routes/[...slug]/+page.svelte +++ b/docs/src/routes/[...slug]/+page.svelte @@ -2,10 +2,10 @@ import type { PageData } from './$types'; import { onMount, type SvelteComponent } from 'svelte'; import { page } from '$app/stores'; - import { base } from '$app/paths'; import '$lib/styles/markdown.scss'; import '$lib/styles/coldark.scss'; + import { base } from '$app/paths'; export let data: PageData; diff --git a/docs/svelte.config.js b/docs/svelte.config.js index 3f812da..0cdd882 100644 --- a/docs/svelte.config.js +++ b/docs/svelte.config.js @@ -1,7 +1,7 @@ import mdsvexConfig from './mdsvex.config.js'; import adapter from '@sveltejs/adapter-static'; import { mdsvex } from 'mdsvex'; -import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'; +import { vitePreprocess } from '@sveltejs/kit/vite'; /** @type {import('@sveltejs/kit').Config} */ const config = { diff --git a/package.json b/package.json index 85b8d68..2239bd7 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "husky": "^8.0.3", "lint-staged": "^13.2.2", "ora": "^6.3.0", - "prettier": "3.1.0", + "prettier": "^3.1.0", "prettier-plugin-svelte": "^3.1.0", "prettier-plugin-tailwindcss": "^0.5.7", "semantic-release": "^20.1.3", @@ -53,5 +53,13 @@ "@semantic-release/npm", "@semantic-release/github" ] + }, + "pnpm": { + "overrides": { + "@adobe/css-tools@<4.3.1": ">=4.3.1", + "semver@>=7.0.0 <7.5.2": ">=7.5.2", + "postcss@<8.4.31": ">=8.4.31", + "undici@<5.26.2": ">=5.26.2" + } } } diff --git a/packages/carta-md/README.md b/packages/carta-md/README.md index 2b4495b..8b68dab 100644 --- a/packages/carta-md/README.md +++ b/packages/carta-md/README.md @@ -1,25 +1,29 @@ -[![Carta.png](https://i.postimg.cc/nV6DMXKM/Carta.png)](https://beartocode.github.io/carta/) +
+ banner +
-

Carta

-
Modern, lightweight, powerful Markdown Editor.
+
+ +
Carta
+
Swiftly edit and render Markdown, with no overhead.

@@ -28,81 +32,38 @@ # Introduction -> **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. +Carta is a **lightweight**, **fast** and **extensible** Svelte Markdown editor and viewer, based on [Marked](https://github.com/markedjs/marked). Check out the [demo](http://beartocode.github.io/carta/) 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. ## Features -- ๐ŸŒˆ 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; -- ๐Ÿ”€ 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 (plugin); -- ๐ŸŒˆ Code blocks **syntax highlighting** (plugin). - -## Packages - -| Package | Status | Docs | -| ----------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | ---------------------------------------------------------------------------- | -| [carta-md](https://www.npmjs.com/package/carta-md) | ![carta-md](https://img.shields.io/npm/v/carta-md) | [/](https://beartocode.github.io/carta/introduction) | -| [plugin-math](https://www.npmjs.com/package/@cartamd/plugin-math) | ![plugin-math](https://img.shields.io/npm/v/@cartamd/plugin-math) | [/plugins/math](https://beartocode.github.io/carta/plugins/math) | -| [plugin-code](https://www.npmjs.com/package/@cartamd/plugin-code) | ![plugin-code](https://img.shields.io/npm/v/@cartamd/plugin-code) | [/plugins/code](https://beartocode.github.io/carta/plugins/code) | -| [plugin-emoji](https://www.npmjs.com/package/@cartamd/plugin-emoji) | ![plugin-emoji](https://img.shields.io/npm/v/@cartamd/plugin-emoji) | [/plugins/emoji](https://beartocode.github.io/carta/plugins/emoji) | -| [plugin-slash](https://www.npmjs.com/package/@cartamd/plugin-slash) | ![plugin-slash](https://img.shields.io/npm/v/@cartamd/plugin-slash) | [/plugins/slash](https://beartocode.github.io/carta/plugins/slash) | -| [plugin-tikz](https://www.npmjs.com/package/@cartamd/plugin-tikz) | ![plugin-tikz](https://img.shields.io/npm/v/@cartamd/plugin-tikz) | [/plugins/tikz](https://beartocode.github.io/carta/plugins/tikz) | -| [plugin-attachment](https://www.npmjs.com/package/@cartamd/plugin-attachment) | ![plugin-attachment](https://img.shields.io/npm/v/@cartamd/plugin-attachment) | [/plugins/attachment](https://beartocode.github.io/carta/plugins/attachment) | -| [plugin-anchor](https://www.npmjs.com/package/@cartamd/plugin-anchor) | ![plugin-anchor](https://img.shields.io/npm/v/@cartamd/plugin-anchor) | [/plugins/anchor](https://beartocode.github.io/carta/plugins/anchor) | - -## Community plugins - -| Plugin | Description | -| ----------------------------------------------------------------------------- | ---------------------------------- | -| [carta-plugin-video](https://github.com/maisonsmd/carta-plugin-video) | Render online videos | -| [carta-plugin-imsize](https://github.com/maisonsmd/carta-plugin-imsize) | Render images in specific sizes | -| [carta-plugin-subscript](https://github.com/maisonsmd/carta-plugin-subscript) | Render subscripts and superscripts | -| [carta-plugin-ins-del](https://github.com/maisonsmd/carta-plugin-ins-del) | `` and `` tags support | +- 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). # Getting started -> **WARNING** +> **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 - -Core package: - -``` -npm i carta-md -``` - -Plugins: - -``` -npm i @cartamd/plugin-name -``` ## Basic configuration ```svelte - + ``` @@ -137,33 +97,7 @@ For the full documentation, examples, guides and more checkout the [website](htt - [Slash](https://beartocode.github.io/carta/plugins/slash) - [TikZ](https://beartocode.github.io/carta/plugins/tikz) - [Attachment](https://beartocode.github.io/carta/plugins/attachment) - - [Anchor](https://beartocode.github.io/carta/plugins/anchor) - API: - [Utilities](https://beartocode.github.io/carta/api/utilities) - [Core](https://beartocode.github.io/carta/api/core) - [Extension](https://beartocode.github.io/carta/api/extension) - -# Contributing & Development - -Every contribution is well accepted. If you have a feature request you can open a new issue. - -This package uses a [pnpm workspace](https://pnpm.io/workspaces), so pnpm is required to download and put everything together properly. - -### Committing - -This repository is [commitizen](https://github.com/commitizen/cz-cli) friendly. To commit use: - -``` -npm run commit -# or, if you have commitizen installed globally -git cz -``` - -### Running docs - -If you want to preview the docs: - -``` -cd docs -npm run dev -``` diff --git a/packages/carta-md/package.json b/packages/carta-md/package.json index bc074ef..30eaff3 100644 --- a/packages/carta-md/package.json +++ b/packages/carta-md/package.json @@ -14,7 +14,10 @@ "svelte": "./dist/index.js", "import": "./dist/index.js" }, - "./default.css": "./dist/default.css" + "./default.css": "./dist/default.css", + "./default-theme.css": "./dist/default.css", + "./light.css": "./dist/light.css", + "./dark.css": "./dist/dark.css" }, "version": "3.0.0", "scripts": { @@ -24,23 +27,18 @@ "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch" }, "devDependencies": { - "@sveltejs/adapter-auto": "^3.1.1", - "@sveltejs/kit": "^2.5.4", - "@sveltejs/package": "^2.3.0", - "@sveltejs/vite-plugin-svelte": "^3.0.2", - "svelte-check": "^3.6.7", + "@sveltejs/adapter-auto": "^1.0.0-next.90", + "@sveltejs/kit": "^1.0.0-next.587", + "@sveltejs/package": "^2.0.2", + "svelte-check": "^3.2.0", "tslib": "^2.4.1", "typescript": "^5.1.6", - "vite": "^5.1.6" + "typescript-plugin-css-modules": "^5.0.1" }, "type": "module", "dependencies": { - "rehype-stringify": "^10.0.0", - "remark-gfm": "^4.0.0", - "remark-parse": "^11.0.0", - "remark-rehype": "^11.1.0", - "shiki": "^1.4.0", - "unified": "^11.0.4" + "@speed-highlight/core": "1.2.2", + "marked": "^9.1.5" }, "peerDependencies": { "svelte": "^3.54.0 || ^4.0.0" diff --git a/packages/carta-md/src/lib/MarkdownEditor.svelte b/packages/carta-md/src/lib/CartaEditor.svelte similarity index 70% rename from packages/carta-md/src/lib/MarkdownEditor.svelte rename to packages/carta-md/src/lib/CartaEditor.svelte index 8e8cb33..9595047 100644 --- a/packages/carta-md/src/lib/MarkdownEditor.svelte +++ b/packages/carta-md/src/lib/CartaEditor.svelte @@ -1,12 +1,9 @@ - - -
-
- - -