MDsveX

repository·main·Indexed 25 days ago

https://github.com/pngwn/mdsvex

A Markdown preprocessor for Svelte that enables developers to write Markdown as Svelte components. The project includes a monorepo of tools for parsing and manipulating Svelte/Markdown ASTs via the svast specification, including svelte-parse, svast-stringify, and svast-utils. It supports .svx and .svelte.md files, allowing Svelte components to be used within Markdown and vice versa.

Tokens
7.1K
Snippets
12
Records
49
Agent score
84%

What's inside mdsvex

  1. Overview of MDsveX

    main
    MDsveX is a Markdown preprocessor for Svelte that allows you to use Markdown syntax directly within Svelte components. It enables a workflow where Markdown files can be treated as Svelte components.
  2. Install and use MDsveX for Svelte components

    main

    MDsveX is a markdown preprocessor for Svelte components, similar to MDX for React. It enables you to use Svelte components directly within your markdown files, or embed markdown content within your Svelte components. This allows for highly interactive documentation and content pages.

    <script>
      import { Chart } from '../components/Chart.svelte';
    </script>
    
    # Here’s a chart
    
    The chart is rendered inside our MDsveX document.
    
    <Chart />
  3. Understand the svast Abstract Syntax Tree (AST) architecture

    main

    svast (Svelte Abstract Syntax Tree) is an AST implementation that follows the Unist specification.

    Key architectural characteristics:

    • Unist Compliance: It implements the Unist spec for syntax trees.
    • Naming Convention: All node types that implement a unique interface are camelCased and prefixed with svelte.
    • Language Agnostic: The AST is designed to be language agnostic and does not impose opinions on the contents of expressions.
    • Node Hierarchy: It extends base Unist nodes to provide Svelte-specific syntax support.
  4. Develop a Svelte project

    main

    After creating your project and installing dependencies (using npm install, pnpm install, or yarn), start the development server using the dev script. You can use the --open flag to automatically open the application in a new browser tab.

    npm run dev
    
    # or start the server and open the app in a new browser tab
    npm run dev -- --open
  5. Create a new Svelte project with sv

    main

    Use the sv CLI (powered by @sveltejs/cli) to scaffold a new Svelte project. You can either initialize the project in the current directory or specify a new directory name.

    # create a new project in the current directory
    npx sv create
    
    # create a new project in my-app
    npx sv create my-app
  6. Install mdsvex packages via pkg.pr.new

    main

    You can install specific versions of mdsvex packages directly from the pkg.pr.new tool using their unique URLs. This is useful for accessing experimental templates or specific package builds. Available packages include mdsvex, pfm-parse, svast, svast-stringify, svast-utils, and svelte-parse.

    npm i https://pkg.pr.new/pngwn/MDsveX/mdsvex@e9631f1
    npm i https://pkg.pr.new/pngwn/MDsveX/pfm-parse@e9631f1
    npm i https://pkg.pr.new/pngwn/MDsveX/svast@e9631f1
    npm i https://pkg.pr.new/pngwn/MDsveX/svast-stringify@e9631f1
    npm i https://pkg.pr.new/pngwn/MDsveX/svast-utils@e9631f1
    npm i https://pkg.pr.new/pngwn/MDsveX/svelte-parse@e9631f1
  7. Configure layouts and layoutPropForwarding

    main

    You can define layouts for your mdsvex files using the layout option.

    • Single Layout: Pass a string path to apply one layout to all files.
    • Named Layouts: Pass an object where keys are layout names and values are file paths. This enables layout_mode: 'named'.

    Use layoutPropForwarding to control how props are passed to these layouts:

    • 'legacy': Standard Svelte prop forwarding.
    • 'runes': Optimized for Svelte 5 runes.

    Note: If you use named layouts, you can specify the layout in the file's frontmatter.

  8. Use mdsvex as a Svelte preprocessor

    main

    Integrate mdsvex into your Svelte project by adding it to your svelte.config.js preprocessors array. This allows you to use .svx files (or other extensions) that combine Markdown with Svelte components.

    Configuration Options

    OptionTypeDefaultDescription
    extensionstring'.svx'The default extension to use for mdsvex files.
    extensionsstring[][extension]A list of extensions to treat as mdsvex files.
    layoutstring | Record<string, string> | falsefalseA single path to a layout file, or an object mapping layout names to file paths.
    frontmatterobjectundefinedOptions for parsing frontmatter (e.g., type, marker, parse).
    highlightobject{ highlighter: code_highlight, optimise: true }Syntax highlighting options.
    smartypantsboolean | objecttrueSmart typography options.
    remarkPluginsUnifiedPlugins[]Remark plugins to apply to the Markdown AST.
    rehypePluginsUnifiedPlugins[]Rehype plugins to apply to the HTML AST.
    layoutPropForwarding'legacy' | 'runes''legacy'Determines how props are forwarded to layouts.

    Example Usage

    import { mdsvex } from 'mdsvex';
    
    /** @type {import('svelte').Config} */
    const config = {
      preprocess: [
        mdsvex({
          extensions: ['.svx', '.md'],
          layout: './src/layouts/Post.svelte',
          remarkPlugins: [],
          rehypePlugins: []
        })
      ]
    };
    
    export default config;
  9. Remove positional data with `cleanPositions`

    main

    The cleanPositions function removes all position data from every node in a tree. This is useful for reducing tree size when positional information is no longer required.

    Key behaviors:

    • Mutation: This is a destructive operation. It returns the exact same tree instance passed in, with all position properties deleted.

    Signature:

    • cleanPositions(tree: Node): Node
    import { cleanPositions } from 'svast-utils';
    
    const tree = {
      type: 'root',
      children: [
        {
          type: 'hello',
          position: { start: { ... }, end: { ... } }
        },
        {
          type: 'hello',
          position: { start: { ... }, end: { ... } }
        },
        {
          type: 'somethingelse' ,
          children: [ ... ],
          position: { start: { ... }, end: { ... }}
        },
      ],
      position: { start: { ... }, end: { ... }}
    }
    
    const clean_tree = cleanPositions(tree);
    
    // clean_tree === tree === { 
    //   type: 'root',
    //   children: [
    //     { type: 'hello' },
    //     { type: 'hello' },
    //     { 
    //       type: 'somethingelse' ,
    //       children: [ ... ],
    //     },
    //   ],
    // }
  10. Walk a svast tree with `walk`

    main

    The walk function traverses a svast tree (or a svast-compatible tree), executing a callback for every node visited.

    Key behaviors:

    • Mutation: The operation is not immutable; it returns the exact same tree instance passed in, mutated if necessary.
    • Callback Arguments: The callback receives (node, parent). For the root node, parent is undefined.
    • Bailing out: Returning false from the callback prevents walk from visiting the children of the current node, but sibling nodes will still be walked.
    • Recursion: The function uses recursion; extremely large trees may cause stack overflow issues.

    Signatures:

    • walk(tree: Node, cb: walkCallback): Node
    • walkCallback(node: Node, parent: Node | undefined): void | boolean
    import { walk } from 'svast-utils';
    
    const tree = {
      type: 'root',
      children: [
        { type: 'hello' },
        { type: 'hello' },
        { type: 'somethingelse' , children: [ ... ]},
      ]
    }
    
    const node_names = [];
    
    walk(tree, (node, parent) => {
      node_names.push(node.type);
      // this will prevent the children of this node from being walked
      if (node.type === 'somethingelse') return false;
    })
    
    // node_names === ['root', 'hello', 'hello', 'somethingelse']