├── .github ├── codeowners ├── release.yml ├── CONTRIBUTING.md └── workflows │ └── release.yaml ├── packages ├── markdown │ ├── src │ │ ├── utils │ │ │ ├── types.ts │ │ │ ├── index.ts │ │ │ └── escape.ts │ │ ├── plugins │ │ │ ├── remark │ │ │ │ ├── index.ts │ │ │ │ └── html.ts │ │ │ ├── index.ts │ │ │ ├── rehype │ │ │ │ ├── index.ts │ │ │ │ ├── components.ts │ │ │ │ ├── highlight │ │ │ │ │ ├── types.ts │ │ │ │ │ ├── utils.ts │ │ │ │ │ └── index.ts │ │ │ │ ├── code.ts │ │ │ │ └── layouts.ts │ │ │ ├── utils.ts │ │ │ └── types.ts │ │ ├── shared │ │ │ ├── index.ts │ │ │ ├── meta.ts │ │ │ └── is.ts │ │ ├── index.ts │ │ ├── types │ │ │ └── index.ts │ │ ├── compile │ │ │ ├── types │ │ │ │ ├── index.ts │ │ │ │ ├── compile.ts │ │ │ │ ├── file.ts │ │ │ │ ├── entries.ts │ │ │ │ ├── layouts.ts │ │ │ │ ├── highlight.ts │ │ │ │ └── frontmatter.ts │ │ │ ├── entries.ts │ │ │ ├── layouts.ts │ │ │ ├── module.ts │ │ │ ├── instance.ts │ │ │ ├── file.ts │ │ │ └── index.ts │ │ ├── config │ │ │ ├── index.ts │ │ │ └── types.ts │ │ └── preprocessor │ │ │ └── index.ts │ ├── tsconfig.json │ ├── .gitignore │ ├── .prettierignore │ ├── README.md │ ├── bundler.config.ts │ ├── LICENSE.txt │ └── package.json └── unplugins │ ├── src │ ├── rehype │ │ ├── index.ts │ │ ├── types.ts │ │ └── shiki │ │ │ ├── utils.ts │ │ │ ├── index.ts │ │ │ └── types.ts │ ├── index.ts │ ├── remark │ │ ├── index.ts │ │ ├── types.ts │ │ ├── reading-stats │ │ │ ├── types.ts │ │ │ ├── stats.ts │ │ │ └── index.ts │ │ └── toc │ │ │ ├── types.ts │ │ │ └── index.ts │ └── types.ts │ ├── tsconfig.json │ ├── .gitignore │ ├── .prettierignore │ ├── README.md │ ├── bundler.config.ts │ ├── LICENSE.txt │ └── package.json ├── .gitattributes ├── pnpm-workspace.yaml ├── prettier.config.mjs ├── media └── cover.png ├── playgrounds └── sveltekit │ ├── src │ ├── components │ │ ├── index.ts │ │ ├── button │ │ │ ├── index.ts │ │ │ └── Button.svelte │ │ └── header │ │ │ ├── index.ts │ │ │ ├── HeaderMain.svelte │ │ │ └── NavMain.svelte │ ├── content │ │ ├── components │ │ │ ├── index.ts │ │ │ └── MarkdownTitle.md │ │ └── layouts │ │ │ └── default │ │ │ ├── components │ │ │ ├── index.ts │ │ │ ├── H2.svelte │ │ │ └── H3.svelte │ │ │ └── layout.svelte │ ├── routes │ │ ├── +page.svelte │ │ ├── +layout.svelte │ │ ├── +error.svelte │ │ ├── docs │ │ │ └── +page.md │ │ ├── +layout.ts │ │ ├── blog │ │ │ └── +page.md │ │ ├── about │ │ │ └── +page.md │ │ └── support │ │ │ └── +page.md │ ├── app.html │ ├── hooks.server.ts │ ├── app.d.ts │ └── styles │ │ └── app.css │ ├── static │ └── favicons │ │ └── icon-512.png │ ├── vite.config.ts │ ├── .prettierignore │ ├── .gitignore │ ├── tsconfig.json │ ├── package.json │ ├── svelte.config.js │ └── markdown.config.js ├── .gitignore ├── .prettierignore ├── CHANGELOG.md ├── .vscode ├── settings.json └── extensions.json ├── eslint.config.mjs ├── .editorconfig ├── LICENSE.txt ├── package.json ├── README.md └── pnpm-lock.yaml /.github/codeowners: -------------------------------------------------------------------------------- 1 | * @ivodolenc 2 | -------------------------------------------------------------------------------- /packages/markdown/src/utils/types.ts: -------------------------------------------------------------------------------- 1 | export * from './' 2 | -------------------------------------------------------------------------------- /packages/markdown/src/utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from './escape' 2 | -------------------------------------------------------------------------------- /packages/unplugins/src/rehype/index.ts: -------------------------------------------------------------------------------- 1 | export * from './shiki' 2 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * linguist-vendored 2 | *.ts linguist-vendored=false 3 | -------------------------------------------------------------------------------- /packages/markdown/src/plugins/remark/index.ts: -------------------------------------------------------------------------------- 1 | export * from './html' 2 | -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - 'packages/*' 3 | - 'playgrounds/*' 4 | -------------------------------------------------------------------------------- /prettier.config.mjs: -------------------------------------------------------------------------------- 1 | export { default } from '@sveltek/prettier-config' 2 | -------------------------------------------------------------------------------- /media/cover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveltek/markdown/HEAD/media/cover.png -------------------------------------------------------------------------------- /packages/markdown/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@sveltek/tsconfig" 3 | } 4 | -------------------------------------------------------------------------------- /packages/unplugins/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@sveltek/tsconfig" 3 | } 4 | -------------------------------------------------------------------------------- /packages/markdown/src/shared/index.ts: -------------------------------------------------------------------------------- 1 | export * from './meta' 2 | export * from './is' 3 | -------------------------------------------------------------------------------- /packages/unplugins/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './remark' 2 | export * from './rehype' 3 | -------------------------------------------------------------------------------- /packages/markdown/src/plugins/index.ts: -------------------------------------------------------------------------------- 1 | export * from './remark' 2 | export * from './rehype' 3 | -------------------------------------------------------------------------------- /packages/unplugins/src/rehype/types.ts: -------------------------------------------------------------------------------- 1 | export * from './shiki/types' 2 | 3 | export * from './' 4 | -------------------------------------------------------------------------------- /packages/unplugins/src/remark/index.ts: -------------------------------------------------------------------------------- 1 | export * from './toc' 2 | export * from './reading-stats' 3 | -------------------------------------------------------------------------------- /playgrounds/sveltekit/src/components/index.ts: -------------------------------------------------------------------------------- 1 | export * from './header' 2 | export * from './button' 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | *.log* 4 | .private 5 | .cache 6 | .env 7 | .npmrc 8 | dist 9 | -------------------------------------------------------------------------------- /playgrounds/sveltekit/src/components/button/index.ts: -------------------------------------------------------------------------------- 1 | export { default as Button } from './Button.svelte' 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | *-lock.* 4 | *.log* 5 | .private 6 | .cache 7 | .env 8 | dist 9 | -------------------------------------------------------------------------------- /playgrounds/sveltekit/src/components/header/index.ts: -------------------------------------------------------------------------------- 1 | export { default as HeaderMain } from './HeaderMain.svelte' 2 | -------------------------------------------------------------------------------- /packages/markdown/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | *.log* 4 | .private 5 | .cache 6 | .env 7 | .npmrc 8 | dist 9 | -------------------------------------------------------------------------------- /playgrounds/sveltekit/src/content/components/index.ts: -------------------------------------------------------------------------------- 1 | export { default as MarkdownTitle } from './MarkdownTitle.md' 2 | -------------------------------------------------------------------------------- /packages/unplugins/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | *.log* 4 | .private 5 | .cache 6 | .env 7 | .npmrc 8 | dist 9 | -------------------------------------------------------------------------------- /packages/markdown/.prettierignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | *-lock.* 4 | *.log* 5 | .private 6 | .cache 7 | .env 8 | dist 9 | -------------------------------------------------------------------------------- /packages/unplugins/.prettierignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | *-lock.* 4 | *.log* 5 | .private 6 | .cache 7 | .env 8 | dist 9 | -------------------------------------------------------------------------------- /packages/unplugins/src/remark/types.ts: -------------------------------------------------------------------------------- 1 | export * from './toc/types' 2 | export * from './reading-stats/types' 3 | 4 | export * from './' 5 | -------------------------------------------------------------------------------- /packages/unplugins/src/rehype/shiki/utils.ts: -------------------------------------------------------------------------------- 1 | export const isFunction = (v: any): v is (...args: any[]) => unknown => 2 | v instanceof Function 3 | -------------------------------------------------------------------------------- /playgrounds/sveltekit/static/favicons/icon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveltek/markdown/HEAD/playgrounds/sveltekit/static/favicons/icon-512.png -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # What's New 2 | 3 | Check out the latest features and improvements. 4 | 5 | #### [Release Notes](https://github.com/sveltek/markdown/releases) 6 | -------------------------------------------------------------------------------- /packages/markdown/src/plugins/rehype/index.ts: -------------------------------------------------------------------------------- 1 | export * from './code' 2 | export * from './layouts' 3 | export * from './components' 4 | export * from './highlight' 5 | -------------------------------------------------------------------------------- /playgrounds/sveltekit/src/content/layouts/default/components/index.ts: -------------------------------------------------------------------------------- 1 | export { default as h2 } from './H2.svelte' 2 | export { default as h3 } from './H3.svelte' 3 | -------------------------------------------------------------------------------- /playgrounds/sveltekit/src/routes/+page.svelte: -------------------------------------------------------------------------------- 1 | 2 | Home page 3 | 4 | 5 |
6 |

Home page

7 |
8 | -------------------------------------------------------------------------------- /packages/markdown/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from '@/config' 2 | export * from '@/plugins/rehype/highlight' 3 | export * from '@/compile' 4 | export * from '@/preprocessor' 5 | -------------------------------------------------------------------------------- /packages/markdown/src/types/index.ts: -------------------------------------------------------------------------------- 1 | export * from '@/compile/types' 2 | export * from '@/config/types' 3 | export * from '@/plugins/types' 4 | 5 | export * from '@' 6 | -------------------------------------------------------------------------------- /packages/markdown/src/shared/meta.ts: -------------------------------------------------------------------------------- 1 | export const meta = { 2 | name: 'svelte-markdown', 3 | layoutName: `Markdown__Layout`, 4 | componentName: `Markdown__Component`, 5 | } 6 | -------------------------------------------------------------------------------- /packages/markdown/src/plugins/utils.ts: -------------------------------------------------------------------------------- 1 | import type { PluginList } from './types' 2 | 3 | export const usePlugins = (plugins: PluginList | undefined): PluginList => 4 | plugins ?? [] 5 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.defaultFormatter": "esbenp.prettier-vscode", 3 | "editor.formatOnSave": true, 4 | "eslint.validate": ["javascript", "typescript", "svelte"] 5 | } 6 | -------------------------------------------------------------------------------- /playgrounds/sveltekit/src/components/header/HeaderMain.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 |
6 | 7 |
8 | -------------------------------------------------------------------------------- /playgrounds/sveltekit/src/components/button/Button.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 | 8 | -------------------------------------------------------------------------------- /playgrounds/sveltekit/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import { sveltekit } from '@sveltejs/kit/vite' 3 | 4 | export default defineConfig({ 5 | plugins: [sveltekit()], 6 | }) 7 | -------------------------------------------------------------------------------- /packages/markdown/src/shared/is.ts: -------------------------------------------------------------------------------- 1 | // Inspired by Hypernym Utils, v3.4.3, MIT License, https://github.com/hypernym-studio/utils 2 | 3 | export { isString, isObject, isArray, isFalse } from '@hypernym/utils' 4 | -------------------------------------------------------------------------------- /playgrounds/sveltekit/.prettierignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | *-lock.* 4 | *.log* 5 | .private 6 | .cache 7 | .env 8 | .svelte-kit 9 | .vercel 10 | dist 11 | /build 12 | /functions 13 | /package -------------------------------------------------------------------------------- /packages/markdown/src/compile/types/index.ts: -------------------------------------------------------------------------------- 1 | export * from './file' 2 | export * from './frontmatter' 3 | export * from './layouts' 4 | export * from './entries' 5 | export * from './highlight' 6 | export * from './compile' 7 | -------------------------------------------------------------------------------- /playgrounds/sveltekit/src/components/header/NavMain.svelte: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "dbaeumer.vscode-eslint", 4 | "esbenp.prettier-vscode", 5 | "EditorConfig.EditorConfig", 6 | "svelte.svelte-vscode", 7 | "hypernym-studio.hypernym-icons" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /eslint.config.mjs: -------------------------------------------------------------------------------- 1 | import { 2 | defineConfig, 3 | jsConfig, 4 | tsConfig, 5 | svelteConfig, 6 | ignoresConfig, 7 | } from '@sveltek/eslint-config' 8 | 9 | export default defineConfig([jsConfig, tsConfig, svelteConfig, ignoresConfig]) 10 | -------------------------------------------------------------------------------- /playgrounds/sveltekit/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | *.log* 4 | .private 5 | .cache 6 | .env 7 | .env.* 8 | .npmrc 9 | .svelte-kit 10 | dist 11 | /build 12 | /functions 13 | /package 14 | vite.config.js.timestamp-* 15 | vite.config.ts.timestamp-* -------------------------------------------------------------------------------- /playgrounds/sveltekit/src/routes/+layout.svelte: -------------------------------------------------------------------------------- 1 | 7 | 8 |
9 | 10 | {@render children()} 11 |
12 | -------------------------------------------------------------------------------- /packages/unplugins/src/types.ts: -------------------------------------------------------------------------------- 1 | export type * as Unified from 'unified' 2 | export type { Plugin } from 'unified' 3 | export type * as VFile from 'vfile' 4 | export type * as Mdast from 'mdast' 5 | export type * as Hast from 'hast' 6 | 7 | export * from './remark/types' 8 | export * from './rehype/types' 9 | -------------------------------------------------------------------------------- /playgrounds/sveltekit/src/routes/+error.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | Error 7 | 8 | 9 |
10 |

{page.status}

11 |

{page.error?.message}

12 |
13 | -------------------------------------------------------------------------------- /playgrounds/sveltekit/src/content/layouts/default/components/H2.svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 |

{@render children?.()}

8 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | indent_size = 2 7 | indent_style = space 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.md] 12 | max_line_length = 0 13 | trim_trailing_whitespace = false 14 | 15 | [COMMIT_EDITMSG] 16 | max_line_length = 0 17 | -------------------------------------------------------------------------------- /playgrounds/sveltekit/src/content/layouts/default/components/H3.svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 |

8 | {@render children?.()} 9 |

10 | -------------------------------------------------------------------------------- /playgrounds/sveltekit/src/routes/docs/+page.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Docs page 3 | description: Get started with Svelte Markdown. 4 | --- 5 | 6 | 9 | 10 | {description} 11 | 12 | ::MarkdownTitle 13 | 14 | ## Heading Level 2 15 | 16 | ### Heading Level 3 17 | -------------------------------------------------------------------------------- /packages/unplugins/src/remark/reading-stats/types.ts: -------------------------------------------------------------------------------- 1 | export interface ReadingStats { 2 | minutes: number 3 | words: number 4 | text: string 5 | } 6 | 7 | export interface ReadingStatsOptions { 8 | /** 9 | * Specifies how many words per minute an average reader can read. 10 | * 11 | * @default 200 12 | */ 13 | wordsPerMinute?: number 14 | } 15 | -------------------------------------------------------------------------------- /playgrounds/sveltekit/src/routes/+layout.ts: -------------------------------------------------------------------------------- 1 | import { error } from '@sveltejs/kit' 2 | import type { LayoutLoad } from './$types' 3 | 4 | export const prerender = true 5 | 6 | export const load: LayoutLoad = async ({ url }) => { 7 | if (!url.pathname) { 8 | error(404, { 9 | message: `Could not find ${url.pathname}.`, 10 | }) 11 | } 12 | 13 | return {} 14 | } 15 | -------------------------------------------------------------------------------- /playgrounds/sveltekit/src/app.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | %sveltekit.head% 8 | 9 | 10 |
%sveltekit.body%
11 | 12 | 13 | -------------------------------------------------------------------------------- /playgrounds/sveltekit/src/routes/blog/+page.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Blog page 3 | description: Read the latest news. 4 | layout: false 5 | entry: blog 6 | --- 7 | 8 | ## What's New 9 | 10 | ## Featured Posts 11 | 12 | ### Updates 13 | 14 | ### News 15 | 16 | ### Q&A 17 | 18 | --- 19 | 20 | 25 | -------------------------------------------------------------------------------- /packages/markdown/README.md: -------------------------------------------------------------------------------- 1 |

@sveltek/markdown

2 | 3 |

Svelte Markdown Preprocessor.

4 | 5 |
6 | 7 | ## Contribute 8 | 9 | Check out the quick [guide](https://github.com/sveltek/markdown/blob/main/.github/CONTRIBUTING.md) for more info. 10 | 11 | ## License 12 | 13 | Developed in 🇭🇷 Croatia, © Sveltek. 14 | 15 | Released under the [MIT](LICENSE.txt) license. 16 | -------------------------------------------------------------------------------- /playgrounds/sveltekit/src/content/components/MarkdownTitle.md: -------------------------------------------------------------------------------- 1 | --- 2 | # Here we need to set the layout to false, because we are using the frontmatter global defaults which add the `layout: default` option to all markdown files. 3 | # We could skip this if we weren't using global defaults. 4 | layout: false 5 | --- 6 | 7 | 10 | 11 | ## {title} 12 | -------------------------------------------------------------------------------- /playgrounds/sveltekit/src/hooks.server.ts: -------------------------------------------------------------------------------- 1 | import { dev } from '$app/environment' 2 | import type { Handle } from '@sveltejs/kit' 3 | 4 | export const handle: Handle = async ({ event, resolve }) => { 5 | if ( 6 | dev && 7 | event.url.pathname === '/.well-known/appspecific/com.chrome.devtools.json' 8 | ) { 9 | return new Response(undefined, { status: 404 }) 10 | } 11 | 12 | return await resolve(event) 13 | } 14 | -------------------------------------------------------------------------------- /packages/unplugins/README.md: -------------------------------------------------------------------------------- 1 |

@sveltek/unplugins

2 | 3 |

Sveltek's Unified plugins for Markdown preprocessor.

4 | 5 |
6 | 7 | ## Contribute 8 | 9 | Check out the quick [guide](https://github.com/sveltek/markdown/blob/main/.github/CONTRIBUTING.md) for more info. 10 | 11 | ## License 12 | 13 | Developed in 🇭🇷 Croatia, © Sveltek. 14 | 15 | Released under the [MIT](LICENSE.txt) license. 16 | -------------------------------------------------------------------------------- /playgrounds/sveltekit/src/app.d.ts: -------------------------------------------------------------------------------- 1 | declare global { 2 | namespace App { 3 | // interface Error {} 4 | // interface Locals {} 5 | // interface PageData {} 6 | // interface Platform {} 7 | 8 | declare module '*.md' { 9 | import type { Component } from 'svelte' 10 | 11 | declare const MarkdownComponent: Component 12 | 13 | export default MarkdownComponent 14 | } 15 | } 16 | } 17 | 18 | export {} 19 | -------------------------------------------------------------------------------- /playgrounds/sveltekit/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./.svelte-kit/tsconfig.json", 3 | "compilerOptions": { 4 | "target": "ESNext", 5 | "module": "ESNext", 6 | "moduleResolution": "Bundler", 7 | "allowJs": true, 8 | "checkJs": true, 9 | "esModuleInterop": true, 10 | "forceConsistentCasingInFileNames": true, 11 | "resolveJsonModule": true, 12 | "skipLibCheck": true, 13 | "sourceMap": true, 14 | "strict": true 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /packages/unplugins/src/remark/toc/types.ts: -------------------------------------------------------------------------------- 1 | export interface TocOptions { 2 | /** 3 | * Specifies the maximum headings depth to be included in the table of content. 4 | * 5 | * @default 3 6 | */ 7 | depth?: number 8 | /** 9 | * Specifies whether headings include link tags. 10 | * 11 | * @default true 12 | */ 13 | links?: boolean 14 | } 15 | 16 | export interface TocItem { 17 | id: string 18 | depth: number 19 | value: string 20 | } 21 | 22 | export type TocItems = TocItem[] 23 | -------------------------------------------------------------------------------- /packages/markdown/src/plugins/types.ts: -------------------------------------------------------------------------------- 1 | import type { PluggableList } from 'unified' 2 | export type { Plugin } from 'unified' 3 | 4 | export type PluginList = PluggableList 5 | 6 | export interface Plugins { 7 | remark?: PluginList 8 | rehype?: PluginList 9 | } 10 | 11 | export type * as Unified from 'unified' 12 | export type * as VFile from 'vfile' 13 | export type * as Mdast from 'mdast' 14 | export type * as Hast from 'hast' 15 | 16 | export * from './rehype/highlight' 17 | export * from './rehype/highlight/types' 18 | -------------------------------------------------------------------------------- /playgrounds/sveltekit/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "playground-sveltekit", 3 | "version": "0.0.0", 4 | "author": "Sveltek", 5 | "private": true, 6 | "type": "module", 7 | "scripts": { 8 | "dev": "vite", 9 | "build": "vite build", 10 | "preview": "vite preview", 11 | "sync": "svelte-kit sync", 12 | "format:play": "prettier --write ." 13 | }, 14 | "devDependencies": { 15 | "@sveltejs/adapter-static": "^3.0.9", 16 | "shiki": "^3.12.2", 17 | "svelte-check": "^4.3.1", 18 | "vite": "^7.1.4" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /packages/markdown/src/compile/types/compile.ts: -------------------------------------------------------------------------------- 1 | import type { MarkdownConfig } from '@/config/types' 2 | 3 | export interface CompileOptions { 4 | filename?: string 5 | config?: MarkdownConfig 6 | /** 7 | * @experimental This option is experimental and may change at any time, so use it with caution. 8 | * 9 | * @default true 10 | */ 11 | htmlTag?: boolean 12 | /** 13 | * @experimental This option is experimental and may change at any time, so use it with caution. 14 | * 15 | * @default true 16 | */ 17 | module?: boolean 18 | } 19 | -------------------------------------------------------------------------------- /packages/markdown/src/compile/types/file.ts: -------------------------------------------------------------------------------- 1 | import type { PreprocessorGroup } from 'svelte/compiler' 2 | import type { Plugins } from '@/plugins/types' 3 | import type { Frontmatter } from './frontmatter' 4 | import type { Layout } from './layouts' 5 | 6 | export interface ASTScript { 7 | start: number 8 | end: number 9 | content: string 10 | } 11 | 12 | export interface FileData { 13 | preprocessors?: PreprocessorGroup[] 14 | plugins?: Plugins 15 | dependencies?: string[] 16 | frontmatter?: Frontmatter 17 | components?: string[] 18 | layout?: Layout 19 | } 20 | -------------------------------------------------------------------------------- /packages/unplugins/src/remark/reading-stats/stats.ts: -------------------------------------------------------------------------------- 1 | import type { ReadingStats } from './types' 2 | 3 | interface Options { 4 | wordsPerMinute?: number 5 | } 6 | 7 | const countWords = (text: string): number => (text.match(/\S+/g) || []).length 8 | 9 | export const readingStats = ( 10 | text: string, 11 | { wordsPerMinute = 200 }: Options = {}, 12 | ): ReadingStats => { 13 | const words = countWords(text) 14 | const min = words / wordsPerMinute 15 | const minutes = min < 1 ? 1 : Math.round(min * 10) / 10 16 | 17 | return { minutes, words, text: `${minutes} min read` } 18 | } 19 | -------------------------------------------------------------------------------- /playgrounds/sveltekit/svelte.config.js: -------------------------------------------------------------------------------- 1 | import adapter from '@sveltejs/adapter-static' 2 | import { svelteMarkdown } from '../../packages/markdown/dist/index.mjs' 3 | import { markdownConfig } from './markdown.config.js' 4 | 5 | /** @type {import('@sveltejs/kit').Config} */ 6 | const config = { 7 | kit: { 8 | adapter: adapter({ 9 | fallback: '404.html', 10 | }), 11 | alias: { 12 | $: 'src', 13 | }, 14 | }, 15 | preprocess: [svelteMarkdown(markdownConfig)], 16 | extensions: ['.svelte', '.md'], 17 | compilerOptions: { 18 | runes: true, 19 | }, 20 | } 21 | 22 | export default config 23 | -------------------------------------------------------------------------------- /.github/release.yml: -------------------------------------------------------------------------------- 1 | changelog: 2 | categories: 3 | - title: Breaking Changes 4 | labels: 5 | - breaking-change 6 | - break 7 | - title: New Features 8 | labels: 9 | - feat 10 | - title: Bug Fixes 11 | labels: 12 | - fix 13 | - title: Types 14 | labels: 15 | - types 16 | - dts 17 | - title: Refactoring Code 18 | labels: 19 | - refactor 20 | - title: Tests 21 | labels: 22 | - test 23 | - title: Documentation 24 | labels: 25 | - docs 26 | - title: Other Changes 27 | labels: 28 | - '*' 29 | -------------------------------------------------------------------------------- /playgrounds/sveltekit/src/styles/app.css: -------------------------------------------------------------------------------- 1 | html { 2 | margin: 0; 3 | padding: 0; 4 | background-color: black; 5 | color: white; 6 | font-family: sans-serif; 7 | } 8 | 9 | a, 10 | a:visited { 11 | color: white; 12 | text-decoration: none; 13 | } 14 | 15 | pre[data-line-numbers='true'] { 16 | counter-reset: step; 17 | counter-increment: step 0; 18 | 19 | .line::before { 20 | content: counter(step); 21 | counter-increment: step; 22 | opacity: 0.5; 23 | display: inline-flex; 24 | align-items: center; 25 | justify-content: flex-end; 26 | width: 1rem; 27 | margin-right: 0.5rem; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /packages/markdown/src/utils/escape.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Escapes certain Svelte special characters in a string, replacing them with their corresponding HTML entity codes. 3 | * 4 | * Ensures that the string can safely be used in templates or code. 5 | * 6 | * @example 7 | * 8 | * ```ts 9 | * import { escapeSvelte } from '@sveltek/markdown/utils' 10 | * 11 | * escapeSvelte(value) 12 | * ``` 13 | */ 14 | export function escapeSvelte(value: string): string { 15 | return value 16 | .replace( 17 | /[{}`]/g, 18 | (v) => ({ '{': '{', '}': '}', '`': '`' })[v] || v, 19 | ) 20 | .replace(/\\([trn])/g, '\$1') 21 | } 22 | -------------------------------------------------------------------------------- /packages/unplugins/bundler.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig, externals } from '@hypernym/bundler' 2 | import { dependencies, devDependencies } from './package.json' 3 | 4 | export default defineConfig({ 5 | entries: [ 6 | // Main 7 | { 8 | input: './src/index.ts', 9 | externals: [ 10 | ...externals, 11 | ...Object.keys(dependencies), 12 | ...Object.keys(devDependencies), 13 | ], 14 | }, 15 | { 16 | dts: './src/types.ts', 17 | output: './dist/index.d.mts', 18 | externals: [ 19 | ...externals, 20 | ...Object.keys(dependencies), 21 | ...Object.keys(devDependencies), 22 | ], 23 | }, 24 | ], 25 | }) 26 | -------------------------------------------------------------------------------- /packages/markdown/src/plugins/rehype/components.ts: -------------------------------------------------------------------------------- 1 | import { visit } from 'unist-util-visit' 2 | import { meta } from '@/shared' 3 | import type { Root } from 'hast' 4 | import type { FileData } from '@/compile/types' 5 | import type { Plugin } from '@/plugins/types' 6 | 7 | export const rehypeCreateComponents: Plugin<[], Root> = () => { 8 | return (tree, vfile) => { 9 | const data = vfile.data as FileData 10 | const { layout, components } = data 11 | 12 | if (!layout || !components) return 13 | 14 | visit(tree, 'element', (node) => { 15 | if (components.includes(node.tagName)) { 16 | node.tagName = `${meta.componentName}.${node.tagName}` 17 | } 18 | }) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /packages/markdown/src/compile/entries.ts: -------------------------------------------------------------------------------- 1 | import { isObject } from '@/shared' 2 | import type { MarkdownConfig } from '@/config/types' 3 | import type { FileData, Entry } from './types' 4 | 5 | export function getEntryData( 6 | data: FileData, 7 | config: MarkdownConfig = {}, 8 | ): Entry | undefined { 9 | const { entry } = data.frontmatter! 10 | 11 | if (!config.entries || !entry) return 12 | 13 | const entryName = isObject(entry) ? entry.name : entry 14 | 15 | const entryConfig = config.entries[entryName] 16 | if (!entryConfig) { 17 | throw new TypeError( 18 | `Invalid entry name. Valid names are: ${Object.keys(config.entries).join(', ')}.`, 19 | ) 20 | } 21 | 22 | return entryConfig 23 | } 24 | -------------------------------------------------------------------------------- /packages/markdown/src/plugins/rehype/highlight/types.ts: -------------------------------------------------------------------------------- 1 | import type { Element } from 'hast' 2 | 3 | export interface HighlighterData { 4 | lang: string | undefined 5 | meta: string | undefined 6 | code: string | undefined 7 | } 8 | 9 | export type Highlighter = ( 10 | data: HighlighterData, 11 | ) => Promise | string | undefined 12 | 13 | export interface HighlightOptions { 14 | /** 15 | * Specifies custom syntax highlighter. 16 | * 17 | * @default undefined 18 | */ 19 | highlighter?: Highlighter 20 | /** 21 | * Specifies custom options for the `root` node (usually the `
` tag).
22 |    *
23 |    * @default undefined
24 |    */
25 |   root?: (node: Element) => void
26 | }
27 | 


--------------------------------------------------------------------------------
/playgrounds/sveltekit/src/routes/about/+page.md:
--------------------------------------------------------------------------------
 1 | ---
 2 | title: About page
 3 | description: Svelte Markdown Preprocessor.
 4 | layout: false
 5 | entry: about
 6 | specialElements: true
 7 | ---
 8 | 
 9 | 
10 | 
11 |   Custom Title - {title}
12 |   
13 | 
14 | 
15 | 
18 | 
19 | 
26 | 
27 | {description}
28 | 
29 |